1053

这是由语言定义的吗?有定义的最大值吗?不同浏览器有区别吗?

4

22 回答 22

950

JavaScript 有两种数字类型:NumberBigInt.

最常用的数字类型Number是 64 位浮点IEEE 754数字。

该类型的最大精确整数值为Number.MAX_SAFE_INTEGER,即:

  • 2 53 -1,或
  • +/- 9,007,199,254,740,991,或
  • 九千万亿 七万亿 一百九千九十亿 七十四万九百九十一

换个角度来看:1 万亿字节是 PB(或 1000 TB)。

在这种情况下,“安全”是指准确表示整数并正确比较它们的能力。

从规范:

请注意,所有大小不大于 2 53的正整数和负整数都可以在Number类型中表示(实际上,整数 0 有两种表示形式,+0 和 -0)。

要安全地使用大于此的整数,您需要使用BigInt没有上限的 。

请注意,按位运算符和移位运算符对 32 位整数进行操作,因此在这种情况下,最大安全整数为 2 31 -1 或 2,147,483,647。

const log = console.log
var x = 9007199254740992
var y = -x
log(x == x + 1) // true !
log(y == y - 1) // also true !

// Arithmetic operators work, but bitwise/shifts only operate on int32:
log(x / 2)      // 4503599627370496
log(x >> 1)     // 0
log(x | 1)      // 1


关于数字 9,007,199,254,740,992 主题的技术说明:此值有一个精确的 IEEE-754 表示,您可以从变量中分配和读取此值,因此对于小于或等于整数域中非常仔细选择的应用程序这个值,你可以把它当作一个最大值。

在一般情况下,您必须将此 IEEE-754 值视为不精确,因为它是对逻辑值 9,007,199,254,740,992 还是 9,007,199,254,740,993 进行编码是不明确的。

于 2008-11-20T22:53:40.780 回答
483

>= 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

于 2008-11-20T22:52:19.940 回答
118

它是 2 53 == 9 007 199 254 740 992。这是因为Numbers 以浮点形式存储在 52 位尾数中。

最小值为 -2 53

这使得一些有趣的事情发生

Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true

而且也可能很危险:)

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
}

进一步阅读:http ://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

于 2010-12-07T10:40:37.050 回答
65

在 JavaScript 中,有一个数字叫做Infinity.

例子:

(Infinity>100)
=> true

// Also worth noting
Infinity - 1 == Infinity
=> true

Math.pow(2,1024) === Infinity
=> true

对于有关此主题的某些问题,这可能就足够了。

于 2012-01-20T21:42:27.110 回答
41

Jimmy 的回答正确地将连续的 JavaScript 整数谱表示为-90071992547409929007199254740992包括在内(对不起 9007199254740993,你可能认为你是 9007199254740993,但你错了! 下面或jsfiddle中的演示)。

console.log(9007199254740993);

但是,没有答案可以以编程方式找到/证明这一点(除了 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);

于 2012-07-24T21:30:53.543 回答
35

许多较早的答案表明,验证9,007,199,254,740,991是最大和安全的整数9007199254740992 === 9007199254740992 + 1正确的。

但是如果我们继续做积累呢:

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。这就是为什么当数字大于9,007,199,254,740,992时,双精度 64 位二进制格式不能保存奇数:

                            (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 位。

来自维基百科(更多细节,去那里)

IEEE 754 双浮点格式.svg

因此,要使指数部分为 2^52,我们需要设置 e = 1075。

于 2018-03-11T09:43:37.050 回答
34

为了安全

var MAX_INT = 4294967295;

推理

x + 1 === x我想我会很聪明,用更务实的方法找到价值。

我的机器每秒只能计数 1000 万次左右......所以我会在 28.56 年后回复明确的答案。

如果你不能等那么久,我愿意打赌

  • 您的大多数循环不会运行 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);
}());
于 2011-08-24T17:29:35.787 回答
30

简短的回答是“视情况而定”。</p>

如果您在任何地方使用位运算符(或者如果您指的是数组的长度),则范围是:

未签名:0…(-1>>>0)

签:(-(-1>>>1)-1)…(-1>>>1)

(碰巧按位运算符和数组的最大长度被限制为 32 位整数。)

如果您不使用按位运算符或使用数组长度:

签:(-Math.pow(2,53))…(+Math.pow(2,53))

这些限制是由“数字”类型的内部表示所施加的,它通常对应于 IEEE 754 双精度浮点表示。(注意,与典型的有符号整数不同,由于内部表示的特性,负极限的大小与正极限的大小相同,实际上包括0!)

于 2011-07-17T07:13:26.450 回答
29

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
于 2014-03-31T05:52:35.737 回答
13

其他人可能已经给出了通用答案,但我认为给出快速确定它的方法是个好主意:

for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);

在 Chrome 30 中,它在不到一毫秒的时间内给了我 9007199254740992。

它将测试 2 的幂,以找出哪一个在“加”1 时等于他自己。

于 2013-10-05T16:53:03.953 回答
9

您要用于按位运算的任何内容都必须介于 0x80000000(-2147483648 或 -2^31)和 0x7fffffff(2147483647 或 2^31 - 1)之间。

控制台会告诉你 0x80000000 等于 +2147483648,但 0x80000000 & 0x80000000 等于 -2147483648。

于 2012-05-15T07:53:12.297 回答
7

尝试:

maxInt = -1 >>> 1

在 Firefox 3.6 中,它是 2^31 - 1。

于 2010-06-20T12:17:15.407 回答
7

JavaScript 在 ECMAScript 2020 中获得了一种新的数据类型:BigInt. 它引入了具有“n”后缀的数字文字并允许任意精度:

var a = 123456789012345678901012345678901n;

当然,当这样的大整数(可能是无意的)强制转换为数字数据类型时,精度仍然会丢失。

而且,显然,由于内存有限,总是存在精度限制,并且为了分配必要的内存和对如此大的数字执行算术,需要花费时间。

例如,一个十万十进制数字的生成,在完成之前将需要一个明显的延迟:

console.log(BigInt("1".padEnd(100000,"0")) + 1n)

...但它有效。

于 2018-12-28T11:19:23.483 回答
4

我用公式做了一个简单的测试,X-(X+1)=-1,XI 的最大值可以在 Safari、Opera 和 Firefox 上工作(在 OS X 上测试)是 9e15。这是我用于测试的代码:

javascript: alert(9e15-(9e15+1));
于 2008-11-20T23:21:38.540 回答
3

我这样写:

var max_int = 0x20000000000000;
var min_int = -0x20000000000000;
(max_int + 1) === 0x20000000000000;  //true
(max_int - 1) < 0x20000000000000;    //true

与 int32 相同

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;
于 2014-09-25T14:29:12.320 回答
3

让我们找到源头

描述

MAX_SAFE_INTEGER常数的值为9007199254740991(9,007,199,254,740,991 或 ~9 万亿)。该数字背后的原因是 JavaScript 使用IEEE 754中指定的双精度浮点格式数字,并且只能安全地表示 和 之间的数字。-(2^53 - 1)2^53 - 1

在这种情况下,安全是指准确表示整数并正确比较它们的能力。例如,Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2将评估为真,这在数学上是不正确的。有关详细信息,请参阅Number.isSafeInteger()

因为MAX_SAFE_INTEGER它是Number的静态属性,所以您始终将其用作Number.MAX_SAFE_INTEGER,而不是用作您创建的Number对象的属性。

浏览器兼容性

在此处输入图像描述

于 2018-07-18T09:29:25.727 回答
1

在 JavaScript 中,数字的表示是2^53 - 1.

但是,Bitwise operation是基于 计算的32 bits ( 4 bytes ),这意味着如果您超过 32 位移位,您将开始丢失位。

于 2018-12-19T21:47:10.430 回答
0

在谷歌浏览器内置的javascript中,你可以到大约2^1024之前的数字称为无穷大。

于 2012-01-10T01:05:22.770 回答
0

如何找到最大整数值

console.log(2 ** 53 - 1);
console.log(Number.MAX_SAFE_INTEGER);

输出:9007199254740993

在此处输入图像描述

于 2022-03-02T09:29:20.887 回答
-1

斯卡托写道:

您要用于按位运算的任何内容都必须介于 0x80000000(-2147483648 或 -2^31)和 0x7fffffff(2147483647 或 2^31 - 1)之间。

控制台会告诉你 0x80000000 等于 +2147483648,但 0x80000000 & 0x80000000 等于 -2147483648

十六进制是无符号的正值,所以 0x80000000 = 2147483648 - 这在数学上是正确的。如果要使其成为有符号值,则必须右移:0x80000000 >> 0 = -2147483648。你也可以写 1 << 31 。

于 2016-12-24T18:34:55.520 回答
-7

Firefox 3 似乎没有大量数字的问题。

1e+200 * 1e+100 将计算精细到 1e+300。

Safari似乎也没有问题。(作为记录,如果其他人决定对此进行测试,则这是在 Mac 上。)

除非我在一天中的这个时候失去了理智,否则这比 64 位整数要大得多。

于 2008-11-20T23:00:13.607 回答
-7

Node.js 和 Google Chrome 似乎都在使用 1024 位浮点值,所以:

Number.MAX_VALUE = 1.7976931348623157e+308
于 2013-03-21T21:50:45.247 回答