从秒总数的中位数中找到确切的小时,分​​钟,秒数

时间:2019-04-13 06:51:49

标签: javascript median

作为整体挑战的一部分,我需要我的代码来找到代表总秒数的数字数组(具有偶数或奇数个元素)的中位数,并将该数字转换为包含小时,分钟和秒的数组总秒数。该代码运行良好,但未通过测试,尤其是随机测试。在每种情况下,总秒数都比测试显示的少一秒或多一秒。

如何用当前代码解决这个问题,还是应该做一些完全不同的事情?

我曾尝试使用不同的Math方法来处理代码,但仍然遇到秒数比正确答案高一秒的问题。

到目前为止,这是我的代码:

concatInt = [ 3432, 4331, 7588, 8432 ]

let rawMedian = function (){

    if(concatInt.length === 0) return 0;

    concatInt.sort(function(a,b){
    return a-b;
    });

    var half = Math.floor(concatInt.length / 2);

    if (concatInt.length % 2)
    return concatInt[half];

    return (concatInt[half - 1] + concatInt[half]) / 2.0;
}

let toStopwatch = function(){
    let hours;
    let minutes;
    let seconds;

    if (rawMedian()/3600 > 1){
    hours = Math.floor(rawMedian()/3600);
    minutes = ((rawMedian() % 3600)/60);
    seconds = Math.floor((minutes - Math.floor(minutes)) * 60);

        if (seconds === 60){
            seconds = seconds -1;
        }

    } else {
    hours = 0;

    if (rawMedian() > 60){
        minutes = (rawMedian()/60);
        seconds = Math.floor((minutes - Math.floor(minutes)) * 60);

        if (seconds === 60){
            seconds = seconds -1;
        }

    } else {
        minutes = 0;
        seconds = rawMedian()
    }
    }

    let timesArr = [];

    timesArr.push(`${hours.toString()}`, `${Math.floor(minutes).toString()}`, `${seconds.toString()}`);
    return timesArr;
}

此代码的结果为[“ 1”,“ 39”,“ 19”]。但是,在Codewars Kata测试中,上面的代码显示为不正确,因为秒数比预期的秒数多或少。我很乐意根据要求提供完整的代码和涉及的特定Kata,但是上面的代码显然会引起问题。

1 个答案:

答案 0 :(得分:0)

有几个问题,但是前两个可以解释为什么您会相差一秒钟:

  • concatInt数组具有偶数个值时,中位数将为半秒。您没有说那半秒钟应该发生什么,但是您似乎截断了它。要求可能是四舍五入

  • 秒数的计算方式容易出现浮点不精确度错误:

    Math.floor((minutes - Math.floor(minutes)) * 60)
    

    例如,如果minutes为8.6,则在应用Math.floor之前,此表达式的结果将是:35.99999999999998,而不是36。您应避免在那里乘以60。相反,您只能获得像这样的秒数:

    median % 60
    
  • 您反复呼叫rawMedian,这很浪费时间。只需调用一次并将结果存储在变量中以备将来使用。

  • if (seconds === 60)条件为真永远不会发生。该代码可以删除。
  • 您使用的其他if构造也是不必要的。中位数是否大于1与计算无关。
  • 奇怪的是,小时,分钟和秒应该作为字符串而不是数字返回。如果确实如此,那么使用模板文字调用toString()方法就太过分了。两种策略之一就足够了。

因此,假设中位数应为四舍五入,则代码如下所示:

const toStopwatch = function() {
    // Call rawMedian only once.
    // Round it (or if it needs to be truncated, use Math.floor).
    const median = Math.round(rawMedian());
    // Calculation of seconds should just be a modulo 60.
    // No special cases need to be distinguished.
    // Do not cast to strings, unless explicitly required
    return [
        Math.floor(median / 3600),        // hours
        Math.floor((median % 3600) / 60), // minutes
        median % 60                       // seconds
    ];
}