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


1108

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


83
如果您不知道,则javascript中的所有数字都是浮点数。从规格:
一些

6
4.3.20数字类型:数字类型是代表数字的一组值。在ECMAScript中,一组值表示双精度64位格式IEEE 754值,包括特殊的“非数字”(NaN)值,正无穷大和负无穷大。
一些

9
是的,Javascript没有明显的“整数”类型,但是进行此转换仍然很常见。例如,在我的应用程序中,用户键入了一个数字(可能包括美分)。我不得不截断美分并显示w /逗号。步骤1是将其转换为int。
mcherm

1
也是有用的:所有方法的速度比较jsperf.com/math-floor-vs-math-round-vs-parseint/33
C ^ ..

1
@karl:如果我接受字段的输入,则可以控制接受的字符,但是我可以用Javascript进行各种处理,而不仅仅是接受用户输入。即使那样,我可能还是想要它来支持粘贴。
mcherm 2012年

Answers:


1606
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

82
如另一个答案中所述,可以使用进行负安全截断var intValue = ~~floatValue;。如果该符号对您的口味不太了解,请将其隐藏在以下函数中:function toInt(value) { return ~~value; }。(如果您愿意的话,这也会将字符串转换为整数。)
Keen 2013年

4
如果此答案具有示例输入/输出,将不满意​​。
J. Random Coder 2015年

7
关于注释,将值限制为32位带符号整数,而Math.floor / ceil / round最多可以处理53位(Number.MAX_SAFE_INTEGER 9007199254740991)。下面的答案中提到了这一点,但是对于那些阅读这些评论的人来说,这里值得重复。
约翰

2
从下面的几个地方阅读:Math.trunc(val);注释,因为这是公认的答案
老巴德曼·格雷(Badman Gray)

不适用于精确的精度,例如2.3 - 2.3 % 1
Lapys

301

按位或运算符

可以使用按位或运算符截断浮点数,它既可以用于正数也可以用于负数:

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

@FabioPoloni:是的,非常简单,似乎按位运算符是最快的。尤其是OR运算符始终是与NOT和Math运算经常匹配的最快的运算符,尽管当您必须支持负数时,Math运算也是最慢的,因为它增加了对数字符号的检查。
罗伯特·科里特尼克

9
@thefourtheye:除无符号右移以外的所有按位运算都对有符号的32位整数起作用。因此,对浮点值使用按位运算会将其转换为整数,并在小数点后去除数字。
罗伯特·科里特尼克

3
如果您只需要正数,Math.floor()则速度会更快(至少根据我在Google Chrome浏览器上进行的首次JSPerf测试,版本30.0.1599.101而言)更快,更可靠(因为它不取决于数字以位表示的方式),可能会更改并可能破坏此按位解决方案),而且最重要的是更明确。
ma11hew28

8
请注意,按位运算符对32位数字进行运算。它们不适用于无法容纳32位的数字。
2013年

2
~~更好,因为它是一元运算符。4.2|0+4相等4~~4.2+4相等8
Janus Troelsen

94

注意:您不能将Math.floor()其用作截断的替代品,因为Math.floor(-3.1) = -4而不是-3!!

截断的正确替代是:

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

    return Math.floor(value);
}

1
这取决于负数的期望行为。有些用法需要负数以映射到更大的负值(-3.5-> -4),而有些用法则需要它们映射到较小的整数(-3.5-> -3)。前者通常称为“地板”。“截断”一词通常用于描述任一行为。就我而言,我只会给它提供负数。但是对于那些关心负数行为的人来说,此注释是一个有用的警告。
mcherm

28
@mcherm:然后他们似乎无法正确理解术语“截断”。截断确实按照其名称的含义执行:截断数字。从一般意义上讲,它永远不等同于地板或天花板。cn.wikipedia.org/wiki/Truncation
Thanatos'4

5
Math.trunc(value)是在ECMAScript 6
4esn0k

2
floor取整为-infinity,取整truncate为零。(ceil四舍五入为+无限)。
彼得·科德斯

46

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

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

更多细节由James Padolsey提供。


1
对于生产代码来说这可能是一件坏事(因为它很晦涩),但这正是我在JS中对我的<canvas>字体渲染引擎进行代码搜索时所需要的。谢谢!
Kragen Javier Sitaker

10
也可以使用| 0.
Jay Douglass 2012年

17
请注意,这两种方法(~~ n或n | 0)仅适用于2 ^ 31-1或2147483647以下的数字。2147483648或更高版本将返回错误的结果。例如,2147483647 | 0返回-2147483648,而4294967295 | 0返回-1,这几乎绝对不是您想要的。
Ed Bayiates 2012年

40

对于截断:

var intvalue = Math.floor(value);

对于回合:

var intvalue = Math.round(value);

6
Math.floor不会截断负值。请参阅上面的答案。否则,很好的答案。
oligofren 2012年

如果您对性能感兴趣,请在此处放置一个小测试用例:jsperf.com/dsafdgdfsaf/2(此处var | 0胜)。
Cybolic

25

您可以使用parseInt方法不进行舍入。由于0x(十六进制)和0(八进制)前缀选项,用户输入时要小心。

var intValue = parseInt(floatValue, 10);

1
当您只需要小数的整数部分而不进行四舍五入时,这实际上是有用的。.round,.ceil和.floor都是这样做的。
Judah Gabriel Himango 2012年

1
...甚至简单地将其截断似乎也是最慢的方法。jsperf.com/float-to-int-conversion-comparison
罗伯特·

2
始终将第二个值传递给parseInt,以指定所需的基数。所以,parseInt函数(的floatValue,10)总是得到基地10
蒂姆·代尔

3
尽管这个问题很古老,但这个问题似乎是一个经常被问到的问题,因此我将其作为警告。如果由于大小而使用“ e”表示法表示该值,则只会得到一位数字,而不是预期的数字。例如,parseInt(1000000000000000000000, 10);结果为1,而不是1 000 000 000 000 000 000000。无论如何,该问题明确地不希望“ 转换为字符串并进行解析 ”,尽管那相对较小...;)
Qantas 94 Heavy

4
@ Qantas94Heavy出现此行为的原因是因为parseInt()期望字符串不是数字作为其第一个参数。传递此整数时,它将转换为1e21,然后parseInt解析该字符串1e21,结果为1
Olaf Dietsche 2014年

18

位移0等于除以1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2

4
小提示:>> 0似乎仅适用于< 2 ^ 31-1>>> 0的整数和< 2 ^ 32-1的整数。对于较大的值,它返回0
Romuald Brunet 2014年

@RomualdBrunet,是的,JavaScript清楚地将所有按位操作定义为对32位数字进行操作。那是规范。
亚历克西斯·威尔克

如上面的答案中所述,这与Javascript仅对32位(有符号)整数执行按位运算一样。因此,任何似乎无能为力的位操作(例如,将0移位,将OR替换为0,将AND替换为1和double NOT),仍然需要Javascript解释器才能将值转换为32bit int。
FrankKrumnow


7

这里有很多建议。到目前为止,按位OR似乎是最简单的。这是另一个简短的解决方案,它也可以使用模运算符处理负数。比按位OR可能更容易理解:

intval = floatval - floatval%1;

此方法也适用于高值数字,其中'| 0','~~'或'>> 0'均不能正确工作:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295

如果您提到其他答案,请添加对该答案的参考,或很快勾勒出其想法。
bertl

5

截断

// Math.trunc() is part of the ES6 spec
Math.trunc( 1.5 );  // returns 1
Math.trunc( -1.5 ); // returns -1
// Math.floor( -1.5 ) would return -2, which is probably not what you wanted

为了

Math.round( 1.5 );  // 2
Math.round( 1.49 ); // 1
Math.round( -1.6 ); // -2
Math.round( -1.3 ); // -1


2

如果查看MathJavaScript中的本机对象,您会获得一整套处理数字和值等的函数。

基本上,您想要做的是非常简单的JavaScript本机...

假设您有以下电话号码:

const myValue = 56.4534931;

现在,如果您想将其四舍五入到最接近的数字,只需执行以下操作:

const rounded = Math.floor(myValue);

你会得到:

56

如果要四舍五入到最接近的数字,请执行以下操作:

const roundedUp = Math.ceil(myValue);

你会得到:

57

Math.round可以将其四舍五入为更高或更低的数字,取决于哪个更接近浮点数。

您也可以~~在浮点数后面使用,将浮点数转换为整数。

您可以像~~myValue... 一样使用它


请注意,~~因为如果该数字大于int 32的限制,它将把该值更改为int 32的限制值。
马查多

1

//Convert a float to integer

Math.floor(5.95)
//5

Math.ceil(5.95)
//6

Math.round(5.4)
//5

Math.round(5.5)
//6

Math.trunc(5.5)
//5

//Quick Ways
console.log(5.95| 0)
console.log(~~5.95) 
console.log(5.95 >> 0)
//5


0

我只想指出,您想通过货币进行舍入,而不是舍弃。一分钱的可能性很小,因为4.999452 * 100的四舍五入将为您5提供更具代表性的答案。

最重要的是,不要忘了银行取整,这是一种抵消直接取整带来的轻微积极偏差的方式-您的财务申请可能会要求这样做。

高斯/银行家的JavaScript四舍五入


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.