什么是JavaScript的最高整数值,数字可以达到而不会丢失精度?

时间:2008-11-20 22:47:54

标签: javascript math browser cross-browser

这是由语言定义的吗?是否有定义的最大值?它在不同的浏览器中是不同的吗?

24 个答案:

答案 0 :(得分:815)

+/- 9007199254740991

ECMA Section 8.5 - Numbers

  

注意,幅度不大于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

有关数字9007199254740992的主题的技术说明:该值有一个精确的IEEE-754表示,您可以从变量中分配和读取该值,因此对于非常小心选择的应用程序在小于或等于此值的整数域中,您可以将其视为最大值。

在一般情况下,您必须将此IEEE-754值视为不精确,因为它是否编码逻辑值9007199254740992或9007199254740993是不明确的。

答案 1 :(得分:442)

&gt; = ES6:

Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;

&lt; = ES5

来自the reference

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

答案 2 :(得分:106)

这是2 53 == 9 007 199 254 740 992.这是因为Number被存储为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

答案 3 :(得分:53)

在JavaScript中,有一个名为Infinity的数字。

示例:

(Infinity>100)
=> true

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

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

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

答案 4 :(得分:39)

Jimmy's answer正确表示连续的JavaScript整数频谱为 -9007199254740992 9007199254740992 包含(对不起9007199254740993,您可能认为您是9007199254740993,但您错了!  以下或jsfiddle 中的演示。

document.write(9007199254740993);

然而,没有答案能够以编程方式找到/证明这一点(除了his answer中提到的那个将在28。56年内完成的一个;),所以这里有一个更有效的方法来做到这一点(到确切地说,它更有效率约28.559999999968312年:),以及test fiddle

/**
 * 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);

答案 5 :(得分:32)

为了安全

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);
}());

答案 6 :(得分:28)

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;

答案 7 :(得分:27)

简短的回答是“这取决于。”

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

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

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

(实际上,按位运算符和数组的最大长度限制为32位整数。)

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

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

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

答案 8 :(得分:13)

之前的许多答案都显示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

我们发现在大于 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 和相邻的小数点,然后乘以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. 

现在,因为在双精度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 --| 

现在我们得到 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 --|

因此当数字大于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  --|

小数点后的位值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

// 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"

指数部分的可用范围是多少?格式为它分配了11位。 来自Wiki的完整格式:(有关详细信息,请访问)

IEEE 754 Double Floating Point Format.svg

enter image description here

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

答案 9 :(得分:11)

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

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

在Chrome 30中,我在不到一毫秒的时间内就获得了9007199254740992。

它将测试2的幂,以找到哪一个,何时添加&#39; 1,等于自己。

答案 10 :(得分:7)

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

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

答案 11 :(得分:5)

尝试:

maxInt = -1 >>> 1

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

答案 12 :(得分:4)

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

javascript: alert(9e15-(9e15+1));

答案 13 :(得分:1)

在Google Chrome内置的javascript中,您可以在号码被称为无限之前转到大约2 ^ 1024。

答案 14 :(得分:1)

在撰写本文时,JavaScript正在接收一种新的数据类型:BigInt。这是stage 3的TC39提案。 BigInt在Chrome 67 +,FireFox 67+(需要激活它的选项),Opera 54和Node 10.4.0中可用。它正在Safari中进行,等等。它引入了带有“ n”后缀的数字文字,并允许任意精度:

var a = 123456789012345678901012345678901n;

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

答案 15 :(得分:1)

我这样写:

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;

答案 16 :(得分:1)

让我们进入sources

说明

  

MAX_SAFE_INTEGER常数的值为9007199254740991(9,007,199,254,740,991或〜9万亿次)。该数字背后的原因是,JavaScript使用double-precision floating-point format numbers中指定的IEEE 754,并且只能安全地表示-(253 - 1)253 - 1之间的数字。

     

在此上下文中,安全是指能够精确表示整数并正确比较它们的能力。例如,Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2将得出true,这在数学上是错误的。有关更多信息,请参见Number.isSafeInteger()

     

由于MAX_SAFE_INTEGERNumber的静态属性,因此您始终将其用作Number.MAX_SAFE_INTEGER,而不是创建的Number对象的属性。

浏览器兼容性

enter image description here

答案 17 :(得分:0)

当数字大于2时,即为53的幂。

Math.pow(2, 53)

javascript知道它是一个大整数。然后,javascript将它们存储为“ bigint”,以便与'bigint'==='bigint'进行比较。

将其值存储在Math对象本身中的更安全方法。

const bigInt1 = Math.pow(2, 55)
const bigInt2 = Math.pow(2, 66)
console.log(bigInt1 === bigInt2) // false

答案 18 :(得分:0)

答案 19 :(得分:0)

基本上javascript并不支持很长时间 所以对于它可以表示小于32位的正常值,它将使用int类型容器。对于大于32位的整数值,它使用double。在双重表示中,整数部分为53位,其余为尾数(以保持浮点信息) 因此,您可以使用2^53 - 1,其值为9007199254740991
您可以通过Number.MAX_SAFE_INTEGER

访问代码中使用的值

答案 20 :(得分:0)

Number.MAX_VALUE表示JavaScript中可表示的最大数值。

由于似乎没有人这么说,在 v8 引擎中,31 bits数字和数字的行为存在差异。

如果您有32 bits,您可以使用第一位告诉javascript引擎该数据是什么类型,其余位包含实际数据。这就是 V8 作为31 bis numbers的一个小优化所做的(或曾经做过,我的来源已经过时了)。你有最后一个31 bits是数字值,然后第一个位告诉引擎它是数字还是对象引用。

但是,如果您使用的数字高于31 bits,那么数据将不适合,数字将以64位加倍,优化将不会出现。

以下视频中的底线是:

  

更喜欢可以表示为 31bits 的数字值   整数。

答案 21 :(得分:0)

Scato wrotes:

  

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

     

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

十六进制小数是无符号正值,因此0x80000000 = 2147483648 - 这在数学上是正确的。如果你想让它成为有符号值,你必须右移:0x80000000&gt;&gt; 0 = -2147483648。你可以写1&lt;&lt; 31也是。

答案 22 :(得分:-6)

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

Number.MAX_VALUE = 1.7976931348623157e+308

答案 23 :(得分:-7)

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

1e + 200 * 1e + 100将罚款为1e + 300。

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

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