什么是最好的方法来转换浮点整数在JavaScript?
-
02-07-2019 - |
题
有几种不同的方法对于转换浮点数到整数在JavaScript。我的问题是用什么方法提供了最好的性能,是最兼容的,或者被认为是最好的做法吗?
这里有一些方法,我知道:
var a = 2.5;
window.parseInt(a); // 2
Math.floor(a); // 2
a | 0; // 2
我敢肯定有人在那里。建议?
解决方案
根据 此网站 :
parseInt偶尔用作将浮点数转换为整数的方法。它非常适合该任务,因为如果它的参数是数字类型,它将首先转换为字符串,然后解析为数字...
对于将数字四舍五入为整数,Math.round,Math.ceil和Math.floor之一最好...
其他提示
来自“Javascript:The Good Parts”来自Douglas Crockford:
Number.prototype.integer = function () {
return Math[this < 0 ? 'ceil' : 'floor'](this);
}
这样做是为每个Number对象添加一个方法。
然后你可以这样使用它:
var x = 1.2, y = -1.2;
x.integer(); // 1
y.integer(); // -1
(-10 / 3).integer(); // -3
显然双按位 - 不是最快的方法来放置数字:
var x = 2.5;
console.log(~~x); // 2
曾经是这里的文章,现在获得404: http:// james.padolsey.com/javascript/double-bitwise-not/
Google已将其缓存: http://74.125.155.132/search?q=cache:wpZnhsbJGt0J:james.padolsey.com/javascript/double-bitwise-not/+double+bitwise+not&& ; CD = 1&安培; HL = EN&安培; CT = clnk&安培; GL = US 代码> 德尔>
但是Wayback Machine可以节省一天的时间! http:// web。 archive.org/web/20100422040551/http://james.padolsey.com/javascript/double-bitwise-not/
答案已经给出,但只是要明确。
使用数学库进行此操作。圆形,细胞或地板功能。
parseInt用于将字符串转换为int,而这不是此处所需的
toFixed用于将float转换为字符串,而不是这里需要的
由于Math函数不会对字符串进行任何转换,因此它会比任何其他错误的选择更快。
您可以使用数字(a).toFixed(0);
甚至只是a.toFixed(0);
修改强>
这是四舍五入到0位,与截断略有不同,并且正如其他人所建议的那样,toFixed返回一个字符串,而不是一个原始整数。用于显示目的。
var num = 2.7; // typeof num is "Number"
num.toFixed(0) == "3"
"最佳"方式 取决于 上:
- 四舍五入的方式:什么样的 类型四舍五入 (浮到整数)你期望的/需要
为积极和/或负数,有一个小数部分。
常见例子:float | trunc | floor | ceil | near (half up) ------+-------+-------+-------+--------------- +∞ | +∞ | +∞ | +∞ | +∞ +2.75 | +2 | +2 | +3 | +3 +2.5 | +2 | +2 | +3 | +3 +2.25 | +2 | +2 | +3 | +2 +0 | +0 | +0 | +0 | +0 NaN | NaN | NaN | NaN | NaN -0 | -0 | -0 | -0 | -0 -2.25 | -2 | -3 | -2 | -2 -2.5 | -2 | -3 | -2 | -2 -2.75 | -2 | -3 | -2 | -3 -∞ | -∞ | -∞ | -∞ | -∞
对于浮到整数转换我们 常 希望 "截断"
(aka "圆对零" aka "圆远离无穷").
实际上这只是扒掉'的分数的一部分浮点数。
大多数技术和(国内)建造方法的行为这种方式。 - 输入:怎么你的(floating point)号码表示:
String
通常基数/基础:10(小)- 浮点('内部')
Number
- 输出:你想要做什么用得到的价值:
- (中级)输出
String
(默认基10)(在屏幕) - 执行的进一步计算得的数值
- (中级)输出
- 范围:
在什么样的数值范围你预期/入计算结果
而对于其范围内做到你希望相应的"正确"的输出。
只 后 这些考虑因素是回答,我们可以考虑适当的方法(s)和速度!
每写262规格: 所有 数量(类型
Number
)在javascript代表/存放在:"IEEE754双精度浮点(binary64)"格式。
所以整数 还 代表在 同 浮点的格式(如数字没有一个分数)。
注:大多数实现 做 使用更有效率(速度和存储器大小)整数类型 内部 当可能的!
作为这种格式存储1号位,11个指数位和第53显着的位("的尾数"),我们可以说: 只 Number
-值 之间 -252
和 +252
可以有一小部分。
换句话说: 所有 表现的积极和消极 Number
-值 之间 252
(几乎) 2(211/2=1024)
(在这一点上,该格式的电话吗 一天 Infinity
)是已经整数(国内圆,因为没有任何位左表示剩余的分数和/或少重大的整数)。
并且有第一个'问题':
你不能控制的内部四舍五入的模式 Number
-结果为建立在文字/串的浮动转换(四舍五入的模式:IEEE754-2008"轮到最近,关系甚至")和内在的算术运算(四舍五入的模式:IEEE754-2008"轮到最近").
例如:
252+0.25 = 4503599627370496.25
是圆形的和存储为: 4503599627370496
252+0.50 = 4503599627370496.50
是圆形的和存储为: 4503599627370496
252+0.75 = 4503599627370496.75
是圆形的和存储为: 4503599627370497
252+1.25 = 4503599627370497.25
是圆形的和存储为: 4503599627370497
252+1.50 = 4503599627370497.50
是圆形的和存储为: 4503599627370498
252+1.75 = 4503599627370497.75
是圆形的和存储为: 4503599627370498
252+2.50 = 4503599627370498.50
是圆形的和存储为: 4503599627370498
252+3.50 = 4503599627370499.50
是圆形的和存储为: 4503599627370500
以控制四舍五入你的 Number
需要一个小数部分(并且至少有一位代表),否则ceil/底/小数部分保留/接近返回的整你送入它。
正确ceil/底/小数部分保留多达x重要的小数位数的(s),我们只在乎如果相对应的最低和最高的十进制分数值仍会给我们一个二元的分数值之后,四舍五入(所以不是天花板或地板的以下一整数)。
因此,举例来说,如果你期望的'正确'的四舍五入(对ceil/底/小数部分保留)达到1显着的小数位数字(x.1 to x.9
),我们需要 至少 3位(4)给我们 一个 二进制小数值:
0.1
更接近 1/(23=8)=0.125
比 0
和 0.9
更接近 1-1/(23=8)=0.875
比 1
.
只 起来 ±2(53-3=50)
将所有表现的价值观有一个非零二进制分数不多的 第一 大大小小数位数字(值 x.1
要 x.9
).
对2小数 ±2(53-6=47)
, 3小数 ±2(53-9=44)
, 为4位小数 ±2(53-13=40)
, 为5个小数 ±2(53-16=37)
, 6小数 ±2(53-19=34)
, ,用于7个小数 ±2(53-23=30)
, 8小数 ±2(53-26=27)
, 为9个小数 ±2(53-29=24)
, 10小数 ±2(53-33=20)
, 11小数 ±2(53-36=17)
, 等等..
一个 "安全Integer" 在javascript是一个整数:
- 那可以 到底 表示如IEEE-754双精确数目,
- 其IEEE-754表示 不能 是因为四舍五入的任何其他的整,以适应IEEE-754表示
(即使±253
(作为一个确切的力量2)可以确切地表示, 不 一个安全的整数,因为它也可能已经±(253+1)
之前,它是圆形的,以适合进入最大的53最显着的位)。
这有效地定义了一个子集的范围(安全表示)整数 之间 -253
和 +253
:
- 自:
-(253 - 1) = -9007199254740991
(含)
(a不断提供静态的酒店Number.MIN_SAFE_INTEGER
由于ES6) 为:
+(253 - 1) = +9007199254740991
(含)
(a不断提供静态的酒店Number.MAX_SAFE_INTEGER
由于ES6)
微不足道提供填充代码,用于2个新的ES6constants:Number.MIN_SAFE_INTEGER || (Number.MIN_SAFE_INTEGER= -(Number.MAX_SAFE_INTEGER=9007199254740991) //Math.pow(2,53)-1 );
由于ES6还有一个免费静态的方法 Number.isSafeInteger()
这测试如果传递的价值的类型 Number
并且是一个整数在内的安全整数的范围(返回布尔 true
或 false
).
注:还将返回 false
为: NaN
, Infinity
并且很显然 String
(即使这表示一个数)。
提供填充代码 例:
Number.isSafeInteger || (Number.isSafeInteger = function(value){
return typeof value === 'number' &&
value === Math.floor(value) &&
value < 9007199254740992 &&
value > -9007199254740992;
});
写2015/ES6提供了一个新的静态的方法 Math.trunc()
截断浮到整数:
返回的组成部分的数量x,消除任何小数位数字。如果x已经是一个整数,结果是x。
或者把简单的(MDN):
不同于其他三个数学的方法:
Math.floor()
,Math.ceil()
和Math.round()
, 方式Math.trunc()
工作很简单和直截了当的:
只截断点和数字背后,无论是否参数是一个积极的数量或一个负数。
我们可以进一步解释(和提供填充代码) Math.trunc()
作为这样的:
Math.trunc || (Math.trunc = function(n){
return n < 0 ? Math.ceil(n) : Math.floor(n);
});
注意,上面提供填充代码的有效载荷可以 潜在的 可以更好地预先进行优化发动机比较:
Math[n < 0 ? 'ceil' : 'floor'](n);
使用: Math.trunc(/* Number or String */)
输入:(整数或浮点) Number
(但是会很乐意尽量转换成一串数字)
输出:(Integer) Number
(但是将愉快地试图转换成数字符串串上下文)
范围: -2^52
要 +2^52
(除此之外,我们应该期待'四舍五入的-错误'(和在某一点上科学/指数表示)普通而简单的因为我们的 Number
输入在IEEE754已经丢失的分精度:因为之间的数字 ±2^52
要 ±2^53
都已经 国内圆 整数(例如 4503599627370509.5
内部已经表示为 4503599627370510
)和之外 ±2^53
在整数也松散的精确度(2)).
浮到整数,转换减去的 剩余部分 (%
)的一个事业部通过 1
:
例如: result = n-n%1
(或 n-=n%1
)
这也应该 截断 浮动。由于其余的运营商已经更高 优先 比减我们有效地获得: (n)-(n%1)
.
对于正数字很容易看出,该楼的价值: (2.5) - (0.5) = 2
,
为负数,这ceils的价值: (-2.5) - (-0.5) = -2
(因为 --=+
所以 (-2.5) + (0.5) = -2
).
由于 输入 和 输出 都 Number
我们 应该 得到的 同样有用的范围和产出 相比ES6 Math.trunc()
(或者是提供填充代码).
注:艰难我 恐惧 (未定)可能有差异:因为我们正在做算术(其境内使用四舍五入的方式"nearTiesEven"(又名银行家的四舍五入))的原始数(float)和第二衍生的人数(分数),这似乎邀请配合digital_representation和算术四舍五入错误,从而有可能返回浮动之后的所有..
浮到整数,转换(ab)使用 bitwise operations:
这个作品 内部 强迫(floating point) Number
转换(截断和溢出)来签署的32位整数值(两个补) 通过使用按位操作 上 Number
(并将结果转化回(floating point) Number
它拥有的只是整数值)。
再次, 输入 和 输出 是 Number
(并再次无声的转换从String-输入到数量和数量产出,以String)。
更重要的艰难(通常被遗忘,没有解释):
根据按位的操作和数字符号, , 有用的 范围 将 限 之间:
-2^31
要 +2^31
(喜欢 ~~num
或 num|0
或 num>>0
) 或 0
要 +2^32
(num>>>0
).
这应该是进一步澄清以下查找表(含有 所有 '重要'的例子):
n | n>>0 OR n<<0 OR | n>>>0 | n < 0 ? -(-n>>>0) : n>>>0 | n|0 OR n^0 OR ~~n | | | OR n&0xffffffff | | ----------------------------+-------------------+-------------+--------------------------- +4294967298.5 = (+2^32)+2.5 | +2 | +2 | +2 +4294967297.5 = (+2^32)+1.5 | +1 | +1 | +1 +4294967296.5 = (+2^32)+0.5 | 0 | 0 | 0 +4294967296 = (+2^32) | 0 | 0 | 0 +4294967295.5 = (+2^32)-0.5 | -1 | +4294967295 | +4294967295 +4294967294.5 = (+2^32)-1.5 | -2 | +4294967294 | +4294967294 etc... | etc... | etc... | etc... +2147483649.5 = (+2^31)+1.5 | -2147483647 | +2147483649 | +2147483649 +2147483648.5 = (+2^31)+0.5 | -2147483648 | +2147483648 | +2147483648 +2147483648 = (+2^31) | -2147483648 | +2147483648 | +2147483648 +2147483647.5 = (+2^31)-0.5 | +2147483647 | +2147483647 | +2147483647 +2147483646.5 = (+2^31)-1.5 | +2147483646 | +2147483646 | +2147483646 etc... | etc... | etc... | etc... +1.5 | +1 | +1 | +1 +0.5 | 0 | 0 | 0 0 | 0 | 0 | 0 -0.5 | 0 | 0 | 0 -1.5 | -1 | +4294967295 | -1 etc... | etc... | etc... | etc... -2147483646.5 = (-2^31)+1.5 | -2147483646 | +2147483650 | -2147483646 -2147483647.5 = (-2^31)+0.5 | -2147483647 | +2147483649 | -2147483647 -2147483648 = (-2^31) | -2147483648 | +2147483648 | -2147483648 -2147483648.5 = (-2^31)-0.5 | -2147483648 | +2147483648 | -2147483648 -2147483649.5 = (-2^31)-1.5 | +2147483647 | +2147483647 | -2147483649 -2147483650.5 = (-2^31)-2.5 | +2147483646 | +2147483646 | -2147483650 etc... | etc... | etc... | etc... -4294967294.5 = (-2^32)+1.5 | +2 | +2 | -4294967294 -4294967295.5 = (-2^32)+0.5 | +1 | +1 | -4294967295 -4294967296 = (-2^32) | 0 | 0 | 0 -4294967296.5 = (-2^32)-0.5 | 0 | 0 | 0 -4294967297.5 = (-2^32)-1.5 | -1 | +4294967295 | -1 -4294967298.5 = (-2^32)-2.5 | -2 | +4294967294 | -2
注1:最后一列已经扩展范围 0
要 -4294967295
使用 (n < 0 ? -(-n>>>0) : n>>>0)
.
注2:按位引入了它自己的转换开销(s)(严重程度vs Math
取决于实际执行情况,因此按位 可能 能快速(通常是在旧的历史浏览器)).
显然,如果您的'浮动指数是一个
String
要开始,parseInt(/*String*/, /*Radix*/)
会是一个适当的选择,以分析它变成一个整数 Number
.parseInt()
将 截断 以及(积极和负面的数字)。的 范围 再次限于IEEE754双精度浮点如上文所解释的
Math
方法(s)。
最后,如果你有一个 String
并期望 String
作为输出你也可以砍的基点和部分(这也给了你一个较精确的截断的范围相比IEEE754双精度浮点(±2^52
))!
额外的:
从上述信息你现在应该有所有你需要知道的。
例如,如果你想要的 圆从零 (aka 圆对无穷)你可能会修改的 Math.trunc()
提供填充代码, 例:
Math.intToInf || (Math.intToInf = function(n){
return n < 0 ? Math.floor(n) : Math.ceil(n);
});
var i = parseInt(n, 10);
如果你没有指定像那样的基数值'010'
将被视为八进制(因此结果将是 8
而不是 10 代码>)。
使用按位运算符。它可能不是转换为整数的最清晰的方法,但它适用于任何类型的数据类型。
假设您的函数采用参数 value
,并且该函数的工作方式是 value
必须始终为整数(并且接受0)。然后,以下任何一项都将 value
指定为整数:
value = ~~(value)
value = value | 0;
value = value & 0xFF; // one byte; use this if you want to limit the integer to
// a predefined number of bits/bytes
最好的部分是,这适用于数字 ~~(&quot; 123.45&quot;)=== 123
的字符串(您可能从文本输入中得到的内容等)。任何非数字值都会产生 0
,即
~~(undefined) === 0
~~(NaN) === 0
~~("ABC") === 0
它使用十六进制数字作为字符串(带 0x
前缀)
~~("0xAF") === 175
我想有一些类型强制。我会做一些性能测试,将它们与 parseInt()
和 Math.floor()
进行比较,但我喜欢没有错误的额外便利代码>被抛出并获得非数字的
0
问题似乎是专门询问从float转换为int。我的理解是这样做的方法是使用 toFixed
。所以......
var myFloat = 2.5;
var myInt = myFloat.toFixed(0);
有没有人知道 Math.floor()
的性能是否比 Number.toFixed()
更多或更少?
你也可以这样做:
var string = '1';
var integer = a * 1;
parseInt()可能是最好的。 a | 0
不能做你真正想要的(如果a是未定义或空值,它只指定0,这意味着一个空对象或数组通过测试),并且Math.floor通过某种类型的技巧工作(它基本上在后台调用parseInt()。