问答中心分类: JAVASCRIPTJavaScript中一个数字在不损失精度的情况下可以达到的最高整数值是多少?
0
匿名用户 提问 7小时 前

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

18 Answers
0
Peter Bailey 回答 7小时 前

>=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
TALlama 回复 7小时 前

我对这个问题进行了编辑,使其更精确地描述了最大整数值,而不仅仅是最大数值。对不起,这里有点混乱。

Pacerier 回复 7小时 前

返回的结果是否保证在所有浏览器上都相等?

Michael Scheper 回复 7小时 前

请注意Number.MIN_VALUE是可能的最小值积极乐观的数字这个最小的价值(即低于任何其他价值)可能是-Number.MAX_VALUE.

Teepeemm 回复 7小时 前

这是最大浮点值。问题是关于最高整数值。而与此同时Number.MAX_VALUE是整数,不能通过2^53在不损失精度的情况下。

Peter Bailey 回复 7小时 前

@Teepeemm这是一个将近六年的问题的六年前的答案,所以奇怪的是你现在会关心尖锐的射击。但是,如果你想看看编辑历史,你会发现原来的问题没有指定整数堆栈溢出。com/posts/307179/revisions,更不用说OP的评论了,他提到要进行编辑/澄清的地方只有4条评论。

superlukas 回复 7小时 前

ES6介绍Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER

rocketsarefast 回复 7小时 前

那么,在这种情况下,我们应该因为更新后的问题错误而投票否决答案,还是因为彼得·贝利在回答问题时是对的而保留它?

Jules 回复 7小时 前

@Pacerier——一个被忽视的好问题:答案恰好是:ECMAscript的所有一致性实现都需要表现为数字存储为IEEE 754双精度浮点数,因此所有实现都应该为这些常数提供相同的答案。

Peter Bailey 回复 7小时 前

@rocketsarefast我更新了答案的文本以包含ES6信息,但你可以随意投票。我认为这里有足够的信息和对话,在这个阶段,对于这么老的问题/答案,投票基本上就像没有行动。

Daira Hopwood 回复 7小时 前

目前的答案是不正确的,因为这意味着MAX\u SAFE\u INTEGER和MAX\u VALUE都回答了这个问题,而区别仅在于ES版本支持它们的地方。事实上,只有MAX\u SAFE\u INTEGER正确回答了当前的问题,只有MAX\u VALUE回答了最初发布的问题。最小安全整数和最小值与精确问题无关。

0
Vjeux 回答 7小时 前

它是253== 9 007 199 254 740 992. 这是因为Numbers以浮点形式存储在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

ninjagecko 回复 7小时 前

虽然在一个合理的时间范围内,一个人永远不会到达for循环的终点,但你可能希望说i += 1000000000

Ted Bigham 回复 7小时 前

@ninjagecko,他从MAX_INT开始,所以终点就在那里。同时使用i+=100000000将使其不再是一个无限循环。试试看。

ninjagecko 回复 7小时 前

@特德·比厄姆:哎呀,我准备得太快了。谢谢你两次纠正我。

T.J. Crowder 回复 7小时 前

参见Jimmy关于9007199254740991而非9007199254740992的论点在这里. 这一点,再加上我的后续行动,似乎很有说服力。

0
BananaNeil 回答 7小时 前

在JavaScript中,有一个数字称为Infinity.
示例:

(Infinity>100)
=> true

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

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

这可能足以回答有关此主题的一些问题。

devios1 回复 7小时 前

有些事情告诉我无穷大不符合整数的条件

djjeck 回复 7小时 前

但这足以初始化min寻找最小值时的变量。

H.Wolper 回复 7小时 前

请注意Infinity - 1 === Infinity

Sijav 回复 7小时 前

还有(无穷<100)=>false和Math。功率(21024)==无穷大

BananaNeil 回复 7小时 前

数学。pow(21024)==无穷大太棒了。我要加上那个。

dmccabe 回复 7小时 前

它处理负无穷大也毫无价值。所以1 - Infinity === -Infinity

user2006656 回复 7小时 前

在数学中,无限不是一个数字,而是一个概念

Laxmikant Dange 回复 7小时 前

最大值:数学。功率(21023)*1.99999998

Andrew 回复 7小时 前

@实际上它是一个整数,等于Infinity - 1 + 1.

0
Briguy37 回答 7小时 前

吉米的回答将连续JavaScript整数频谱正确表示为-90071992547409929007199254740992包容(抱歉9007199254740993,你可能认为你是9007199254740993,但你错了!演示低于或低于J桥).

console.log(9007199254740993);

然而,没有任何答案可以通过编程找到/证明这一点(除了CoolAJ86中提到的答案)他的回答这将在28.56年内完成;),因此,这里有一个更有效的方法来实现这一点(准确地说,它的效率提高了28.55999968312年:),以及一个测试小提琴:

/**
 * 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);
Briguy37 回复 7小时 前

@哈哈,我期待着2040年3月15日。如果我们的数字匹配,我们应该举办一个聚会:)

MickLH 回复 7小时 前

var x=数学。功率(2,53)-3;而(x!=x+1)x++;->9007199254740991

Briguy37 回复 7小时 前

@米克尔:我得到9007199254740992那个密码. 您使用什么JavaScript引擎进行测试?

MickLH 回复 7小时 前

你用自己的代码得到9007199254740992,我没有使用x的最终值,而是出于偏执的原因使用x++的最终值。谷歌Chrome btw。

peterflynn 回复 7小时 前

@MickLH:评估x++给你x的值之前增量已经出现,因此这可能解释了差异。如果希望表达式的计算结果与x的最终值相同,则应将其更改为++x.

MickLH 回复 7小时 前

谢谢,但我确实知道后增量的语义,并使用它的“最终评估”(与x的最终值相反),因为它提供了一个数字,其中(x!=x+1)也称为“最后一个数字,其中+1起作用”,而不是“第一个数字,它失败了”

Briguy37 回复 7小时 前

@米克尔:"last number where +1 works" == "max number w/out losing precision" - 1

MickLH 回复 7小时 前

这个问题有一个公认的答案,所以你对某事的暗示我没有说客观上,要么是错误的,要么是无用的。我评论的目的是为了表明你写的大算法是一种毫无用处的浪费时间,再见,先生。(很抱歉,你对我用一个高度相关的算法解释我的概念表示冒犯,这个算法也有一个对我来说非常有用的目的,而且它确实计算相同的X;)

Briguy37 回复 7小时 前

@米克尔:好吧,我完全误解了你的意思。我认为你的第一个算法是证明9007199254740991是正确的答案。相反,这是为了表明,我的是一个无用的浪费时间。我很高兴我们澄清了。。。

MickLH 回复 7小时 前

但是我爱你,兄弟,不要把它说成我是一个不欣赏效率的邪恶混蛋

Marie 回复 7小时 前

难道你不能从一个大的值开始,在失去精度时只测试较小的值,从而大大加快速度吗?而不是每个循环lol添加1个

0
Carr 回答 7小时 前

许多早期的答案表明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 --|

按照此模式,当数字大于9007199254740992*2=18014398509481984时,只能保留分数的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。