Math.trunc() 没有正确舍入值
Math.trunc() not rounding values properly
我知道在 JavaScript 中肯定有更好的方法来做到这一点,但我只是在做一些我知道的事情。我正在做另一个 Code Wars 挑战,当我应该得到 12:34:56
.
时似乎得到了 12:34:55
对于挑战,函数以几秒钟的格式给出输入,例如。 86399
,然后输出应该是人类可读的格式。
我真的不知道这里出了什么问题,感觉它与 Math.trunc()
有关,因为我的数学是有道理的。
我会解释数学,但它在代码中很容易解释。唯一的问题似乎是秒数。
function humanReadable(seconds) {
const hour = Math.trunc((seconds / 60) / 60);
const mins = Math.trunc((((seconds / 60) / 60) - hour) * 60);
const secs = Math.trunc(((seconds / 60) - Math.trunc(seconds / 60)) * 60);
return `${hour < 10 ? `0${hour}` : hour}:${mins < 10 ? `0${mins}` : mins}:${secs < 10 ? `0${secs}` : secs}`
}
您应该尝试使用模数来计算每次除法后的余数,如下面的代码片段所示。
let d = 86399;
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.trunc(d % 60);
var result = `${h < 10 ? `0${h}` : h}:${m < 10 ? `0${m}` : m}:${s < 10 ? `0${s}` : s}`
console.log(result);
问题是由于浮点数不能准确表示数字
在 45296 的情况下 - 即 12:34:56
A: seconds / 60 = 754.9333333333333
B: Math.trunc(seconds / 60) = 754
A - B (should be 0.9333333333333) = 0.9333333333332803
你可以看到,它比它应该的少,但即使是 0.9333333333333 * 60 也是 55.999999999998 ...截断它,你得到 55
一种解决方法是
const secs = Math.round(((seconds / 60) - Math.trunc(seconds / 60)) * 60);
而且,也许还有
const mins = Math.trunc((((seconds / 60) / 60) - hour) * 60);
会议记录“失败”的案例超过 600 起
Actually, don't do that, it doesn't fix the 600 or so where the minutes are wrong!
更简单的方法是使用 modulo %
运算符
此代码中除法的结果将始终仅为“整数”,因为一旦您去掉 mod 60,除数将始终是 60 的精确倍数(因为这只是之后的余数除以 60) - 数学! :p
function humanReadable(seconds) {
const ss = seconds % 60;
seconds = (seconds - ss) / 60;
const mm = seconds % 60;
const hh = (seconds - mm) / 60;
return [hh,mm,ss].map(v => (''+v).padStart(2, 0)).join(':');
}
console.log(humanReadable(45296))
或者,您可以只使用日期 object 并让它为您完成所有工作
function humanReadable(seconds) {
const d = new Date(0);
d.setUTCSeconds(seconds);
const hh = d.getUTCHours().toString().padStart(2, '0');
const mm = d.getUTCMinutes().toString().padStart(2, '0');
const ss = d.getUTCSeconds().toString().padStart(2, '0');
return `${hh}:${mm}:${ss}`;
}
console.log(humanReadable(45296))
我还包括了另一种获取前导零的方法 - 这只是我的习惯,这些说使用 padStart 等
在 padStart 出现之前,而不是
hour < 10 ? `0${hour}` : hour
我愿意
`0${hour}`.substr(-2)
但是因为你使用的是模板文字,所以你肯定有 padStart :p
我知道在 JavaScript 中肯定有更好的方法来做到这一点,但我只是在做一些我知道的事情。我正在做另一个 Code Wars 挑战,当我应该得到 12:34:56
.
12:34:55
对于挑战,函数以几秒钟的格式给出输入,例如。 86399
,然后输出应该是人类可读的格式。
我真的不知道这里出了什么问题,感觉它与 Math.trunc()
有关,因为我的数学是有道理的。
我会解释数学,但它在代码中很容易解释。唯一的问题似乎是秒数。
function humanReadable(seconds) {
const hour = Math.trunc((seconds / 60) / 60);
const mins = Math.trunc((((seconds / 60) / 60) - hour) * 60);
const secs = Math.trunc(((seconds / 60) - Math.trunc(seconds / 60)) * 60);
return `${hour < 10 ? `0${hour}` : hour}:${mins < 10 ? `0${mins}` : mins}:${secs < 10 ? `0${secs}` : secs}`
}
您应该尝试使用模数来计算每次除法后的余数,如下面的代码片段所示。
let d = 86399;
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.trunc(d % 60);
var result = `${h < 10 ? `0${h}` : h}:${m < 10 ? `0${m}` : m}:${s < 10 ? `0${s}` : s}`
console.log(result);
问题是由于浮点数不能准确表示数字
在 45296 的情况下 - 即 12:34:56
A: seconds / 60 = 754.9333333333333
B: Math.trunc(seconds / 60) = 754
A - B (should be 0.9333333333333) = 0.9333333333332803
你可以看到,它比它应该的少,但即使是 0.9333333333333 * 60 也是 55.999999999998 ...截断它,你得到 55
一种解决方法是
const secs = Math.round(((seconds / 60) - Math.trunc(seconds / 60)) * 60);
而且,也许还有
const mins = Math.trunc((((seconds / 60) / 60) - hour) * 60);
会议记录“失败”的案例超过 600 起
Actually, don't do that, it doesn't fix the 600 or so where the minutes are wrong!
更简单的方法是使用 modulo %
运算符
此代码中除法的结果将始终仅为“整数”,因为一旦您去掉 mod 60,除数将始终是 60 的精确倍数(因为这只是之后的余数除以 60) - 数学! :p
function humanReadable(seconds) {
const ss = seconds % 60;
seconds = (seconds - ss) / 60;
const mm = seconds % 60;
const hh = (seconds - mm) / 60;
return [hh,mm,ss].map(v => (''+v).padStart(2, 0)).join(':');
}
console.log(humanReadable(45296))
或者,您可以只使用日期 object 并让它为您完成所有工作
function humanReadable(seconds) {
const d = new Date(0);
d.setUTCSeconds(seconds);
const hh = d.getUTCHours().toString().padStart(2, '0');
const mm = d.getUTCMinutes().toString().padStart(2, '0');
const ss = d.getUTCSeconds().toString().padStart(2, '0');
return `${hh}:${mm}:${ss}`;
}
console.log(humanReadable(45296))
我还包括了另一种获取前导零的方法 - 这只是我的习惯,这些说使用 padStart 等
在 padStart 出现之前,而不是
hour < 10 ? `0${hour}` : hour
我愿意
`0${hour}`.substr(-2)
但是因为你使用的是模板文字,所以你肯定有 padStart :p