如何在 JavaScript 中将浮点数转换为整数?

IT技术 javascript syntax
2021-02-09 04:26:04

我想在 JavaScript 中将浮点数转换为整数。实际上,我想知道如何进行两种标准转换:截断和舍入。并且有效地,而不是通过转换为字符串和解析。

6个回答
var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue ); 
var intvalue = Math.round( floatvalue );

// `Math.trunc` was added in ECMAScript 6
var intvalue = Math.trunc( floatvalue );

数学对象引用


例子

积极的
// value=x        //  x=5          5<x<5.5      5.5<=x<6  

Math.floor(value) //  5            5            5
Math.ceil(value)  //  5            6            6
Math.round(value) //  5            5            6
Math.trunc(value) //  5            5            5
parseInt(value)   //  5            5            5
~~value           //  5            5            5
value | 0         //  5            5            5
value >> 0        //  5            5            5
value >>> 0       //  5            5            5
value - value % 1 //  5            5            5
消极的
// value=x        // x=-5         -5>x>=-5.5   -5.5>x>-6

Math.floor(value) // -5           -6           -6
Math.ceil(value)  // -5           -5           -5
Math.round(value) // -5           -5           -6
Math.trunc(value) // -5           -5           -5
parseInt(value)   // -5           -5           -5
value | 0         // -5           -5           -5
~~value           // -5           -5           -5
value >> 0        // -5           -5           -5
value >>> 0       // 4294967291   4294967291   4294967291
value - value % 1 // -5           -5           -5
正 - 更大的数字
// x = Number.MAX_SAFE_INTEGER/10 // =900719925474099.1

// value=x            x=900719925474099    x=900719925474099.4  x=900719925474099.5
           
Math.floor(value) //  900719925474099      900719925474099      900719925474099
Math.ceil(value)  //  900719925474099      900719925474100      900719925474100
Math.round(value) //  900719925474099      900719925474099      900719925474100
Math.trunc(value) //  900719925474099      900719925474099      900719925474099
parseInt(value)   //  900719925474099      900719925474099      900719925474099
value | 0         //  858993459            858993459            858993459
~~value           //  858993459            858993459            858993459
value >> 0        //  858993459            858993459            858993459
value >>> 0       //  858993459            858993459            858993459
value - value % 1 //  900719925474099      900719925474099      900719925474099
负数 - 更大的数字
// x = Number.MAX_SAFE_INTEGER/10 * -1 // -900719925474099.1

// value = x      // x=-900719925474099   x=-900719925474099.5 x=-900719925474099.6

Math.floor(value) // -900719925474099     -900719925474100     -900719925474100
Math.ceil(value)  // -900719925474099     -900719925474099     -900719925474099
Math.round(value) // -900719925474099     -900719925474099     -900719925474100
Math.trunc(value) // -900719925474099     -900719925474099     -900719925474099
parseInt(value)   // -900719925474099     -900719925474099     -900719925474099
value | 0         // -858993459           -858993459           -858993459
~~value           // -858993459           -858993459           -858993459
value >> 0        // -858993459           -858993459           -858993459
value >>> 0       //  3435973837           3435973837           3435973837
value - value % 1 // -900719925474099     -900719925474099     -900719925474099
关于注释~~将值限制为 32 位有符号整数,而 Math.floor/ceil/round 最多可以处理 53 位(Number.MAX_SAFE_INTEGER 9007199254740991)。下面的答案中提到了这一点,但对于阅读这些评论的人来说,这里值得重复。
2021-03-16 04:26:04
正如另一个答案中提到的,可以使用var intValue = ~~floatValue;. 如果符号对您的口味来说太晦涩难懂,只需将其隐藏在函数中:function toInt(value) { return ~~value; }(如果您愿意,这也会将字符串转换为整数。)
2021-03-17 04:26:04
从下面几个地方阅读:Math.trunc(val);评论因为这是公认的答案
2021-03-24 04:26:04
如果这个答案有示例输入/输出,会赞成。
2021-03-25 04:26:04
对于像这样的值,不能以精确的精度工作 2.3 - 2.3 % 1
2021-04-01 04:26:04

按位或运算符

按位或运算符可用于截断浮点数,它适用于正数和负数:

function float2int (value) {
    return value | 0;
}

结果

float2int(3.1) == 3
float2int(-3.1) == -3
float2int(3.9) == 3
float2int(-3.9) == -3

性能对比?

我创建了一个JSPerf 测试来比较以下之间的性能:

  • Math.floor(val)
  • val | 0 按位
  • ~~val 按位
  • parseInt(val)

这只适用于正数。在这种情况下,您可以安全地使用按位运算以及Math.floor函数。

但是如果你需要你的代码处理正数和负数,那么按位运算是最快的(或者是首选的)。另一个 JSPerf 测试进行了比较,很明显,由于额外的符号检查,Math 现在是四个中最慢的。

笔记

如评论中所述,BITWISE 运算符对有符号的 32 位整数进行操作,因此将转换大数,例如:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987
@thefourtheye:除无符号右移外的所有按位运算均适用于有符号的 32 位整数。因此,对浮点值使用按位运算会将它们转换为整数,去掉小数点后的数字。
2021-03-13 04:26:04
@FabioPoloni:是的,超级简单,而且按位运算符似乎是最快的。尤其是 OR 运算符总是最快的,通常与 NOT 和 Math 运算匹配,尽管当您还必须支持负数时,Math 运算是最慢的,因为它增加了对数字符号的额外检查。
2021-03-23 04:26:04
如果您只需要正数,Math.floor()则更快(至少根据我在 Google Chrome 版本 30.0.1599.101 上运行您的第一个JSPerf 测试),更健壮(因为它不依赖于数字如何以位表示,这可能会改变并可能破坏这个按位解决方案),最重要的是,更明确。
2021-03-25 04:26:04
请注意,按位运算符对 32 位数字进行操作。它们不适用于太大而无法容纳 32 位的数字。
2021-04-01 04:26:04
~~更好,因为它是一元运算符。4.2|0+4等于4~~4.2+4等于8
2021-04-05 04:26:04

注意:您不能Math.floor()用作 truncate 的替代品,因为Math.floor(-3.1) = -4and not -3!!

truncate 的正确替换是:

function truncate(value)
{
    if (value < 0) {
        return Math.ceil(value);
    }

    return Math.floor(value);
}
Math.trunc(value) 在 ECMAScript 6 中添加
2021-03-18 04:26:04
floor向-无穷大舍入,truncate向零舍入ceil向+无穷大舍入)。
2021-03-19 04:26:04
@mcherm:那么他们似乎没有正确理解“截断”一词。截断正如其名称所暗示的那样:它截断数字。它从不(在一般意义上)等同于 floor 或 ceil。en.wikipedia.org/wiki/截断
2021-03-20 04:26:04
这取决于负数所需的行为。有些用途需要负数来映射到更负的值(-3.5 -> -4),有些需要它们映射到更小的整数(-3.5 -> -3)。前者通常称为“地板”。“截断”一词通常用于描述任一行为。就我而言,我只想给它提供负数。但是对于那些关心负数行为的人来说,这个评论是一个有用的警告。
2021-03-26 04:26:04

按位非运算符可用于截断浮点数。你提到的其他操作都可以通过Math.floorMath.ceilMath.round

> ~~2.5
2
> ~~(-1.4)
-1

更多细节由 James Padolsey 提供。

这也可以用 n | 来完成。0.
2021-04-08 04:26:04
请注意,任一方法(~~n 或 n|0)仅适用于最大为 2^31-1 或 2147483647 的数字。2147483648 或更高版本将返回错误结果;例如,2147483647|0 返回-2147483648,4294967295|0 返回-1,这几乎肯定不是您想要的。
2021-04-08 04:26:04
这对于生产代码来说可能是一件坏事(因为它很模糊),但这正是我在 JS 中对我的<canvas>字体渲染引擎进行代码打球所需要的谢谢!
2021-04-09 04:26:04

对于截断:

var intvalue = Math.floor(value);

对于回合:

var intvalue = Math.round(value);
如果你对性能感兴趣,我在这里放了一个小测试用例:jsperf.com/dsafdgdfsaf/2(var | 0 wins here)。
2021-03-31 04:26:04
Math.floor 不会截断负值。见上面的回答。否则很好的答案。
2021-04-06 04:26:04