作为整体挑战的一部分,我需要我的代码来找到代表总秒数的数字数组(具有偶数或奇数个元素)的中位数,并将该数字转换为包含小时,分钟和秒的数组总秒数。该代码运行良好,但未通过测试,尤其是随机测试。在每种情况下,总秒数都比测试显示的少一秒或多一秒。
如何用当前代码解决这个问题,还是应该做一些完全不同的事情?
我曾尝试使用不同的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,但是上面的代码显然会引起问题。
答案 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
];
}