背景
我正在编写一个函数,该函数接收一个正数,然后将该数字四舍五入到其下面最接近的整数。
我一直在使用Math.floor
,但最近我发现了Math.trunc
。
我知道,在给定正数的情况下,两者都将返回相同的值,并且它们以完全不同的方式工作。 我有兴趣探索这种行为。
问题
- 哪个更快?
- 我应该使用哪一个?
我正在编写一个函数,该函数接收一个正数,然后将该数字四舍五入到其下面最接近的整数。
我一直在使用Math.floor
,但最近我发现了Math.trunc
。
我知道,在给定正数的情况下,两者都将返回相同的值,并且它们以完全不同的方式工作。 我有兴趣探索这种行为。
实际上,有很多其他的方法可以从数字中删除小数。但这是可读性和速度之间的权衡。
选择正确的方法取决于你的需要。如果您只需要删除小数,请始终使用trunc()
或按位运算符。
从概念上讲,floor()
、ceil()
和round()
与trunc()
非常不同。
您已经了解了这些内容,在标准的非关键代码中始终使用它们。
var v = 3.14; [Math.trunc(v), Math.round(v), Math.floor(v), Math.ceil(v)]
// prints results
对于不同的输入值,您会得到以下结果
v t r f c
3.87 : [ 3, 4, 3, 4]
3.14 : [ 3, 3, 3, 4]
-3.14 : [-3, -3, -4, -3]
-3.87 : [-3, -4, -4, -3]
Math.trunc()
截去(truncate)小数点后的数字。
Math.round()
向最接近的整数四舍五入。
Math.floor()
向最接近下方的整数四舍五入。例如:3.5 -> 3
-3.5 -> -4
Math.ceil()
向最接近上方的整数四舍五入。例如:3.5 -> 4
-3.5 -> -3
但这更有趣:)
如果您在代码中查看它们,可能一眼看不出它们的作用,因此在正常代码中不要使用它们。尽管在某些情况下,它们可能会很有用。例如在<canvas/>
中计算坐标。它们速度更快,但有一些限制。
ATTENTION:
Numbers with more than 32 bits get their most significant (leftmost) bits discarded and the leftmost bit becomes the new sign bit.
[ 0b011100110111110100000000000000110000000000001, // 15872588537857 ~~0b011100110111110100000000000000110000000000001, // -1610588159 ~~0b10100000000000000110000000000001, // -1610588159 ]
值
和要将值
移位的位数
作为参数。然而,在截断时,我们总是使用第二个操作数0
、零、false
,不会对原始值做任何改变,除了转换为整数,在以下情况下:
~
非 ~~v
|
或 v | 0
<<
左移 v << 0
>>
有符号右移 v >> 0
>>>
无符号右移 v >>> 0
var v = 3.78;
[ ~~v , v | 0 , v << 0 , v >> 0 , v >>> 0 ]
// prints these results
3.78 : [ 3, 3, 3, 3, 3]
3.14 : [ 3, 3, 3, 3, 3]
-3.74 : [-3, -3, -3, -3, 4294967293]
-3.14 : [-3, -3, -3, -3, 4294967293]
trunc
;) - LuckyLuke SkywalkerMath.trunc
和Math.floor
之间的功能差异,因此我将我的发现放在这个答案中。
Math.trunc
将数字向0
舍入为整数,而Math.floor
将数字向-Infinity
舍入为整数。如下图所示,对于正数,方向相同,而对于负数,方向相反。trunc: towards 0
floor: towards -Infinity
-3 -2 -1 0 1 2 3
-Infinity ... ------+----|--+------+------+------+------+--|----+------ .... Infinity
b a
示例:
var a = 2.3, b = -2.3;
console.log("\t\t\t" + a + "\t\t" + b + "\r\n" + "Math.trunc: " + Math.trunc(a) + "\t\t" + Math.trunc(b) + "\r\n" + "Math.floor: " + Math.floor(a) + "\t\t" + Math.floor(b));
输出:
2.3 -2.3
Math.trunc: 2 -2
Math.floor: 2 -3
var t0 = performance.now();
var result = Math.floor(3.5);
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds to generate:', result);
var t0 = performance.now();
var result = Math.trunc(3.5);
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds to generate:', result);
结果为:花费了0.0300毫秒生成:3 花费了0.0200毫秒生成:3
因此,如果参数仅为正数,则可以使用最快的计算方式。
Math.trunc
,那么你就错了。Math.trunc
是非常新的函数,在每个浏览器中都不被支持。 - Sebastian Simon