TAL*_*ama 923 javascript browser math cross-browser
这是由语言定义的吗?是否有定义的最大值?在不同的浏览器中是不同的?
Jim*_*mmy 841
+/- 9007199254740991
注意,幅度不大于2 53的所有正整数和负整数都可以在Number类型中表示(实际上,整数0有两个表示,+ 0和-0).
它们是64位浮点值,最大精确积分值是2 53 -1,或9007199254740991
.在ES6中,这被定义为Number.MAX_SAFE_INTEGER.
请注意,按位运算符和移位运算符以32位整数运算,因此在这种情况下,最大安全整数为2 31 -1或2147483647.
var x = 9007199254740992;
var y = -x;
x == x + 1; // true !
y == y - 1; // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
x / 2; // 4503599627370496
x >> 1; // 0
x | 1; // 1
Run Code Online (Sandbox Code Playgroud)
有关数字9007199254740992的主题的技术说明:该值有一个精确的IEEE-754表示,您可以从变量中分配和读取该值,因此对于小于或等于整数域的非常仔细选择的应用程序此值,您可以将其视为最大值.
在一般情况下,您必须将此IEEE-754值视为不精确,因为它是否编码逻辑值9007199254740992或9007199254740993是不明确的.
Pet*_*ley 456
> = ES6:
__CODE__
<= ES5
来自参考:
__CODE__
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
Run Code Online (Sandbox Code Playgroud)
Vje*_*eux 108
它是2 53 == 9 007 199 254 740 992.这是因为Number
s在52位尾数中存储为浮点数.
最小值为-2 53.
这会让一些有趣的事情发生
Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true
Run Code Online (Sandbox Code Playgroud)
而且也可能很危险:)
var MAX_INT = Math.pow(2, 53); // 9 007 199 254 740 992
for (var i = MAX_INT; i < MAX_INT + 2; ++i) {
// infinite loop
}
Run Code Online (Sandbox Code Playgroud)
进一步阅读:http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
Ban*_*eil 55
在JavaScript中,有一个叫做的数字Infinity
.
例子:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
Run Code Online (Sandbox Code Playgroud)
对于有关此主题的一些问题,这可能就足够了.
Bri*_*y37 40
吉米的答案正确地表示连续的JavaScript整数谱为-9007199254740992到9007199254740992(抱歉9007199254740993,你可能认为你是9007199254740993,但你错了! 下面或jsfiddle的演示).
console.log(9007199254740993);
Run Code Online (Sandbox Code Playgroud)
然而,没有任何答案能够以编程方式找到/证明这一点(除了CoolAJ86在他的答案中提到的将在28.56 年内完成;),所以这里有一个更有效的方法(确切地说,它更有效率)通过约28.559999999968312年:),以及测试小提琴:
/**
* Checks if adding/subtracting one to/from a number yields the correct result.
*
* @param number The number to test
* @return true if you can add/subtract 1, false otherwise.
*/
var canAddSubtractOneFromNumber = function(number) {
var numMinusOne = number - 1;
var numPlusOne = number + 1;
return ((number - numMinusOne) === 1) && ((number - numPlusOne) === -1);
}
//Find the highest number
var highestNumber = 3; //Start with an integer 1 or higher
//Get a number higher than the valid integer range
while (canAddSubtractOneFromNumber(highestNumber)) {
highestNumber *= 2;
}
//Find the lowest number you can't add/subtract 1 from
var numToSubtract = highestNumber / 4;
while (numToSubtract >= 1) {
while (!canAddSubtractOneFromNumber(highestNumber - numToSubtract)) {
highestNumber = highestNumber - numToSubtract;
}
numToSubtract /= 2;
}
//And there was much rejoicing. Yay.
console.log('HighestNumber = ' + highestNumber);
Run Code Online (Sandbox Code Playgroud)
Coo*_*J86 32
var MAX_INT = 4294967295;
Run Code Online (Sandbox Code Playgroud)
我以为我会聪明一点x + 1 === x
,用更实用的方法找到价值.
我的机器每秒只能计算1000万左右...所以我会在28.56年内回复最终答案.
如果你不能等那么久,我愿意打赌
9007199254740992 === Math.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);
}());
Run Code Online (Sandbox Code Playgroud)
Wai*_*ung 28
ECMAScript 6:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
Run Code Online (Sandbox Code Playgroud)
dan*_*ton 27
简短的回答是"这取决于".
如果您在任何地方使用按位运算符(或者如果您指的是数组的长度),则范围为:
无符号: 0…(-1>>>0)
签: (-(-1>>>1)-1)…(-1>>>1)
(碰巧的是,按位运算符和数组的最大长度限制为32位整数.)
如果您不使用按位运算符或使用数组长度:
签: (-Math.pow(2,53))…(+Math.pow(2,53))
这些限制是由"数字"类型的内部表示强加的,它通常对应于IEEE 754双精度浮点表示.(注意,与典型的有符号整数不同,负极限的大小与正极限的大小相同,这是由于内部表示的特征,实际上包括负 0!)
Car*_*arr 16
之前的许多答案都显示了结果true
,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
Run Code Online (Sandbox Code Playgroud)
我们可以发现,在大于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 --|
Run Code Online (Sandbox Code Playgroud)
在箭头的左侧,我们有位值1和一个相邻的小数点,然后通过相乘2^52
,我们向右移动小数点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.
Run Code Online (Sandbox Code Playgroud)
现在,因为在双精度64位二进制格式中,它严格地为分数分配52位,没有更多位可用于携带以再添加1,所以我们能做的是将所有位设置回0,并进行操作指数部分:
|--> This bit is implicit and persistent.
|
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
|-- 52 bits --| |-- 52 bits --|
(+1)
(radix point has no way to go)
1 . 0000 ---- 0000 * 2^52 * 2 => 1 0000 ---- 0000. * 2
|-- 52 bits --| |-- 52 bits --|
=> 1 . 0000 ---- 0000 * 2^53
|-- 52 bits --|
Run Code Online (Sandbox Code Playgroud)
现在我们得到 9 007 199 254 740 992,并且数字大于它,格式可以容纳的是分数的2倍:
(consume 2^52 to move radix point to the end)
1 . 0000 ---- 0001 * 2^53 => 1 0000 ---- 0001. * 2
|-- 52 bits --| |-- 52 bits --|
Run Code Online (Sandbox Code Playgroud)
因此,当数字大于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
Run Code Online (Sandbox Code Playgroud)
如何[之间号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 --|
Run Code Online (Sandbox Code Playgroud)
小数点后的位值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
Run Code Online (Sandbox Code Playgroud)
少于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
// If the digits exceed 17, JavaScript round it to print it.
//, but the value is 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"
Run Code Online (Sandbox Code Playgroud)
指数部分的可用范围是多少?格式为它分配了11位.来自Wiki的完整格式:(有关详细信息,请访问)
因此,要在指数部分获得2 ^ 52,我们需要设置e = 1075.
Phi*_*e97 11
其他人可能已经给出了通用的答案,但我认为快速确定它是一个好主意:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
Run Code Online (Sandbox Code Playgroud)
在Chrome 30中,我在不到一毫秒的时间内就获得了9007199254740992.
它会测试2的幂来找到哪一个,当'加'1时,等于自己.
小智 7
您想要用于按位运算的任何内容必须介于0x80000000(-2147483648或-2 ^ 31)和0x7fffffff(2147483647或2 ^ 31-1)之间.
控制台将告诉您0x80000000等于+2147483648,但0x80000000和0x80000000等于-2147483648.
在撰写本文时,JavaScript 正在接收一种新的数据类型:BigInt
. 这是第 4 阶段的 TC39 提案,将包含在EcmaScript 2020 中。BigInt
适用于 Chrome 67+、FireFox 68+、Opera 54 和 Node 10.4.0。它正在 Safari 等人中进行......它引入了具有“n”后缀的数字文字并允许任意精度:
var a = 123456789012345678901012345678901n;
Run Code Online (Sandbox Code Playgroud)
当然,当这样的数字被(可能是无意地)强制转换为数字数据类型时,精度仍然会丢失。
而且,显然,由于内存有限,总是存在精度限制,并且为了分配必要的内存和对如此大的数字执行算术需要时间成本。
例如,生成一个十万位十进制数字的数字,在完成之前需要明显的延迟:
console.log(BigInt("1".padEnd(100000,"0")) + 1n)
Run Code Online (Sandbox Code Playgroud)
...但它有效。
小智 5
尝试:
maxInt = -1 >>> 1
Run Code Online (Sandbox Code Playgroud)
在Firefox 3.6中它是2 ^ 31 - 1.