Math.floor VS Math.trunc JavaScript

时间:2016-08-01 15:31:05

标签: javascript performance math

背景

我正在创建一个接收正数的函数,然后将数字四舍五入到它下面最接近的整数。

我一直在使用Math.floor,但最近我发现了Math.trunc

我知道两者都将返回相同的值,给定正数,并且它们以完全不同的方式工作。我有兴趣探索这种行为。

问题

  1. 哪一个更快?
  2. 我应该使用哪一个?

3 个答案:

答案 0 :(得分:28)

实际上,还有更多替代方法可以从数字中删除小数。但这是可读性和速度的权衡。

选择正确的选项取决于您的需求。如果您只需要删除小数,请始终使用trunc()或按位运算符 floor()ceil()round()在概念上与trunc()非常不同。

数学库

你已经知道这些了。始终在标准的非关键代码中使用它们。

var v = 3.14;
[Math.trunc(v), Math.floor(v), Math.ceil(v), Math.round(v)]
// prints results

对于不同的输入值,您可以获得这些结果

          t   f   c   r
 3.87 : [ 3,  3,  4,  4]
 3.14 : [ 3,  3,  4,  3]
-3.14 : [-3, -4, -3, -3]
-3.87 : [-3, -4, -3, -4]

但这更有趣:)

二进制操作和bitwise operators

如果你在代码中查看它们,乍一看它们的作用可能就不那么明显了,所以使用它们。虽然在某些情况下,它们可能有用。例如,计算<canvas/>中的坐标。它们更快,但有限制。

从概念上讲,他们的工作方式如下:

  • 操作数转换为32位整数(超过32位的数字将丢弃其最高有效位。)

按位逻辑运算符

  • 第一个操作数中的每个位与第二个操作数中的相应位配对。 (第一位到第一位,第二位到第二位,依此类推。)
  • 运算符应用于每对位,结果按位构造。

按位移位运算符

  • 这些运算符需要移位valuenumber位位置才能将value移位。

但是,我们始终使用0,零,false作为第二个操作数,在这些情况下对原始值没有任何作用:

~ {NOT {1}}

~~v|

v | 0左移<<

v << 0签名右移>>

v >> 0零填充右移>>>

v >>> 0

性能

https://jsperf.com/number-truncating-methods/1

enter image description here

答案 1 :(得分:2)

现有的答案已经很好地解释了性能。但是,我无法从问题或答案中理解 Math.truncMath.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(Math.trunc(a) + "\t" + Math.floor(a) + "\t" + Math.trunc(b) + "\t" + Math.floor(b));

输出:

2   2   -2  -3

答案 2 :(得分:1)

如果参数是正数,Math.trunc()等同于Math.floor(),  否则Math.trunc()等同于Math.ceil()。

对于性能检查这一个,最快的是Math.trunc

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

所以如果参数只是正数,你可以用最快的数字。