这是由语言定义的吗?有确定的最大值吗?在不同的浏览器中是否有所不同?
当前回答
>= ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
< = ES5
参考文献:
Number.MAX_VALUE;
Number.MIN_VALUE;
console.log (MIN_VALUE, Number.MIN_VALUE); console.log (MAX_VALUE, Number.MAX_VALUE); console.log (MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);/ / ES6 console.log (MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);/ / ES6
其他回答
我用一个公式做了一个简单的测试,X-(X+1)=-1,我在Safari、Opera和Firefox(在OS X上测试)上可以得到的X的最大值是9e15。下面是我用于测试的代码:
javascript: alert(9e15-(9e15+1));
其他人可能已经给出了一般的答案,但我认为给出一个快速确定它的方法会是一个好主意:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
这给了我9007199254740992在Chrome 30不到一毫秒。
它将测试2的幂,以找出当“加”1时,哪一个等于他自己。
在JavaScript中,数字的表示是2^53 - 1。
然而,按位操作是在32位(4个字节)上计算的,这意味着如果你超过32位移位,你将开始丢失位。
许多先前的答案显示9007199254740992 === 9007199254740992 + 1为真,以验证9,007,199,254,740,991是最大且安全的整数。
但如果我们继续积累:
input: 9007199254740992 + 1 output: 9007199254740992 // expected: 9007199254740993
input: 9007199254740992 + 2 output: 9007199254740994 // expected: 9007199254740994
input: 9007199254740992 + 3 output: 9007199254740996 // expected: 9007199254740995
input: 9007199254740992 + 4 output: 9007199254740996 // expected: 9007199254740996
我们可以看到,在大于9,007,199,254,740,992的数字中,只有偶数是可表示的。
这是一个解释双精度64位二进制格式如何工作的条目。让我们看看如何使用这种二进制格式保存(表示)9,007,199,254,740,992。
使用一个简短的版本从4,503,599,627,370,496演示:
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
在箭头的左边,我们有位值1和一个相邻的基数点。通过消耗左边的指数部分,基数点向右移动52步。基数点在最后,我们得到纯二进制的4503599627370496。
现在,让我们继续将分数部分加1,直到所有的位都设置为1,这等于十进制的9,007,199,254,740,991。
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
(+1)
1 . 0000 ---- 0001 * 2^52 => 1 0000 ---- 0001.
(+1)
1 . 0000 ---- 0010 * 2^52 => 1 0000 ---- 0010.
(+1)
.
.
.
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
因为64位双精度格式严格地为分数部分分配了52位,如果我们添加另一个1,就没有更多的位可用了,所以我们可以做的是将所有位设置为0,并操作指数部分:
┏━━▶ This bit is implicit and persistent.
┃
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
|-- 52 bits --| |-- 52 bits --|
(+1)
1 . 0000 ---- 0000 * 2^52 * 2 => 1 0000 ---- 0000. * 2
|-- 52 bits --| |-- 52 bits --|
(By consuming the 2^52, radix
point has no way to go, but
there is still one 2 left in
exponent part)
=> 1 . 0000 ---- 0000 * 2^53
|-- 52 bits --|
现在我们得到9,007,199,254,740,992,对于比它更大的数,格式只能处理2的增量,因为分数部分的每一个增量1最终都会在指数部分乘以左边的2。这就是为什么双精度64位二进制格式不能保存大于9,007,199,254,740,992的奇数:
(consume 2^52 to move radix point to the end)
1 . 0000 ---- 0001 * 2^53 => 1 0000 ---- 0001. * 2
|-- 52 bits --| |-- 52 bits --|
按照这种模式,当数字大于9,007,199,254,740,992 * 2 = 18,014,398,509,481,984时,只能保持4倍的分数:
input: 18014398509481984 + 1 output: 18014398509481984 // expected: 18014398509481985
input: 18014398509481984 + 2 output: 18014398509481984 // expected: 18014398509481986
input: 18014398509481984 + 3 output: 18014398509481984 // expected: 18014398509481987
input: 18014398509481984 + 4 output: 18014398509481988 // expected: 18014398509481988
那么[2 251 799 813 685 248,4 503 599 627 370 496)之间的号码呢?
1 . 0000 ---- 0001 * 2^51 => 1 0000 ---- 000.1
|-- 52 bits --| |-- 52 bits --|
0.1的二进制值正好是2^-1 (=1/2)(=0.5) 因此,当数字小于4,503,599,627,370,496(2^52)时,有一位可用来表示整数的1/2倍:
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
小于2,251,799,813,685,248 (2^51)
input: 2251799813685246.75 output: 2251799813685246.8 // expected: 2251799813685246.75
input: 2251799813685246.25 output: 2251799813685246.2 // expected: 2251799813685246.25
input: 2251799813685246.5 output: 2251799813685246.5
/**
Please note that if you try this yourself and, say, log
these numbers to the console, they will get rounded. JavaScript
rounds if the number of digits exceed 17. The value
is internally held correctly:
*/
input: 2251799813685246.25.toString(2)
output: "111111111111111111111111111111111111111111111111110.01"
input: 2251799813685246.75.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
input: 2251799813685246.78.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
指数部分的取值范围是多少?格式为它分配了11位。
来自维基百科(欲了解更多细节,请访问那里)
为了使指数部分等于2^52,我们需要令e = 1075。
为了安全
var MAX_INT = 4294967295;
推理
我认为我应该聪明一点,用更实用的方法找到x + 1 === x的值。
我的机器每秒只能计算1000万次左右……所以我会在28.56年后给出确切的答案。
如果你等不了那么久,我敢打赌
大多数循环都不会持续28.56年 9007199254740992 ===数学。Pow(2,53) + 1是足够的证明 您应该坚持使用4294967295,即Math.pow(2,32) - 1,以避免预期的位移位问题
求x + 1 === x:
(function () {
"use strict";
var x = 0
, start = new Date().valueOf()
;
while (x + 1 != x) {
if (!(x % 10000000)) {
console.log(x);
}
x += 1
}
console.log(x, new Date().valueOf() - start);
}());
推荐文章
- 在数组中获取所有选中的复选框
- 如何为Firebase构建云函数,以便从多个文件部署多个函数?
- 如何发送推送通知到web浏览器?
- AngularJS:工厂和服务?
- js:将一个组件包装成另一个组件
- 父ng-repeat从子ng-repeat的访问索引
- JSHint和jQuery: '$'没有定义
- 模仿JavaScript中的集合?
- 用JavaScript验证电话号码
- 如何在HTML5中改变视频的播放速度?
- 谷歌地图API v3:我可以setZoom后fitBounds?
- 用jQuery检查Internet连接是否存在?
- ES6/2015中的null安全属性访问(和条件赋值)
- 与push()相反;
- JS字符串“+”vs concat方法