首页 文章

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

提问于
浏览
834

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

21 回答

  • 1

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

    例子:

    (Infinity>100)
    => true
    
    // Also worth noting
    Infinity - 1 == Infinity
    => true
    
    Math.pow(2,1024) === Infinity
    => true
    

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

  • 28

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

    Number.MAX_VALUE = 1.7976931348623157e+308
    
  • 32

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

    document.write(9007199254740993);
    

    然而,没有答案能够以编程方式找到/证明这一点(除了一个CoolAJ86在his answer中提到的将在28 . 56年内完成;),所以这里's a slightly more efficient way to do that (to be precise, it'更有效率约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);
    
  • 0

    之前的许多答案都显示 9007199254740992 === 9007199254740992 + 1 的结果 true
    告诉 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 的数字中,只有偶数是 representable .

    这是一个解释 double-precision 64-bit binary format 如何解决这个问题的条目 . 让我们看看如何使用这种二进制格式保持(表示) 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 --|
    

    在箭头的左侧,我们有 bit value 1 ,并且相邻 radix point ,然后通过乘以 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.
    

    现在,因为在 double-precision 64-bit binary format 中,它严格地为分数分配52位,没有更多的位可用于添加一个1,所以我们可以做的是将所有位设置回0,并操纵指数部分:

    |--> This bit is implicit and persistent.
      |        
      1 . 1111 ---- 1111  *  2^52      =>  1  1111 ---- 1111. 
         |-- 52 bits --|                     |-- 52 bits --|
    
                              (+1)
                                         (radix point have 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 times of the fraction

    (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 times of the fraction

    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 2484 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 times of the integer

    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"
    

    exponent part 的可用范围是多少?格式为它分配了11位 . Wiki的完整格式:(详情请到那里)

    IEEE 754 Double Floating Point Format.svg

    enter image description here

    因此,要在指数部分获得2 ^ 52,我们需要设置e = 1075 .

  • 105

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

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

    >= ES6: Number.MIN_SAFE_INTEGER; Number.MAX_SAFE_INTEGER;

    <= ES5

    来自the referenceNumber.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
    
  • 0

    它是253 == 9 007 199 254 740 992.这是因为 Number 被存储为52位尾数中的浮点数 .

    最小值为-253 .

    这会让一些有趣的事情发生

    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

  • 0

    为了安全起见

    var MAX_INT = 4294967295;
    

    推理

    我以为我会聪明,并且用更务实的方法找到 x + 1 === x 的 Value .

    我的机器每秒只能计算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);
    }());
    
  • 0

    尝试:

    maxInt = -1 >>> 1
    

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

  • 7

    +/- 9007199254740991

    ECMA Section 8.5 - Numbers

    请注意,幅度不大于253的所有正整数和负整数都可以在Number类型中表示(实际上,整数0有两个表示,0和-0) .

    它们是64位浮点值,最大精确积分值是253-1或 9007199254740991 . 在ES6中,这被定义为Number.MAX_SAFE_INTEGER .

    请注意,按位运算符和移位运算符以32位整数运算,因此在这种情况下,最大安全整数为231-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 .

  • 765

    ECMAScript 6:

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

    我这样写:

    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;
    
  • 53

    让我们来看看消息来源

    说明

    MAX_SAFE_INTEGER常量的值为9007199254740991(9,007,199,254,740,991或~9千万亿) . 这个数字背后的原因是JavaScript使用IEEE 754中规定的双精度浮点格式数字,并且只能安全地表示 - (253 - 1)和253 - 1之间的数字 . 在此上下文中的安全是指表示的能力准确地整数并正确地比较它们 . 例如,Number.MAX_SAFE_INTEGER 1 === Number.MAX_SAFE_INTEGER 2将评估为true,这在数学上是不正确的 . 有关更多信息,请参见Number.isSafeInteger() . 因为MAX_SAFE_INTEGER是Number的静态属性,所以始终将其用作Number.MAX_SAFE_INTEGER,而不是您创建的Number对象的属性 .

    浏览器兼容性

    enter image description here

  • 6

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

    1e 200 * 1e 100将计算罚款1e 300 .

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

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

  • 3

    Scato wrotes:

    要用于按位运算的任何内容必须介于0x80000000(-2147483648或-2 ^ 31)和0x7fffffff(2147483647或2 ^ 31 - 1)之间 . 控制台会告诉你0x80000000等于2147483648,但0x80000000和0x80000000等于-2147483648

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

  • 3

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

  • -6

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

  • -7

    简短的回答是“它取决于” .

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

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

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

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

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

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

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

  • 37

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

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

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

    但是,如果您使用 31 bits 以上的数字,那么数据将赢得't fit in, the number will be boxed in 64 bits double and the optimisation won' .

    在下面的视频中,底线是:

    首选可以表示为31位有符号整数的数值 .

  • 11

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

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

    这让我在Chrome 30中不到一毫秒的时间内获得9007199254740992 .

    它将测试2的幂,以找到哪一个,当'添加'1时,等于他自己 .

  • 421

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

    控制台将告诉您0x80000000等于2147483648,但0x80000000和0x80000000等于-2147483648 .

相关问题