IT

숫자가 정확성을 잃지 않고 도달할 수 있는 JavaScript의 최대 정수 값은 얼마입니까?

itgroup 2022. 12. 7. 22:23
반응형

숫자가 정확성을 잃지 않고 도달할 수 있는 JavaScript의 최대 정수 값은 얼마입니까?

이것은 언어로 정의됩니까?정의된 최대값이 있습니까?브라우저마다 다른가요?

JavaScript에는 및 두 가지 번호 유형이 있습니다.

타입은 " " " 입니다.Number는 64비트 부동소수점 IEEE 754 번호입니다.

이 유형의 정확한 최대 적분값은 다음과 같습니다.

  • 2-153 또는
  • +/- 9,007,199,254,740,991 또는
  • 9조 7천 9백 9십억 2천 5백 4십만 7천 9백 1

대략적으로 말하면, 1,000조 바이트는 페타바이트(또는 1,000 테라바이트)입니다.

이 문맥에서 "안전"은 정수를 정확하게 표현하고 그것들을 정확하게 비교할 수 있는 능력을 의미한다.

사양부터:

크기가 2를53 넘지 않는 모든 양의 정수 및 음의 정수는 다음과 같이 표시됩니다.Number은 +표현을 있습니다).type ('0' +0' -0' -2')

이 값보다 큰 정수를 안전하게 사용하려면 상한이 없는 를 사용해야 합니다.

비트 연산자와 시프트 연산자는 32비트 정수로 동작하므로 이 경우 최대 안전 정수는 2-131(2147,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 중 어느 쪽을 부호화하고 있는지 애매하기 때문에 부정확하게 취급해야 합니다.

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

253 == 9 007 199 254 740 992 입니다.그 이유는Number52번입니다.

최소값은 -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 를 참조해 주세요.

JavaScript라는 .Infinity.

예:

(Infinity>100)
=> true

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

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

이 토픽에 관한 몇 가지 질문에는 이것으로 충분할 수 있습니다.

Jimmy의 답변은 연속된 JavaScript 정수 스펙트럼을 -9007199254740992 ~9007199254740992로 올바르게 나타내고 있습니다(죄송합니다만, 9007199254740993이라고 생각하실 수 있습니다만, 틀렸습니다).아래 또는 아래 jsfiddle 데모).

console.log(9007199254740993);

그러나 이를 프로그램적으로 발견/증명할 수 있는 답변은 Cool 이외에는 없습니다.AJ86은 답변에서 28.56년 후에 종료될 것임을 시사했습니다. 따라서 테스트 바이올린과 함께 약간 더 효율적인 방법(정확히 말하면 약 28.5599999968312년)을 제시합니다.

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

에서는, 「아까의 답안」이 많이 나와 .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로 증가시킵니다. 이 값은 10진수로는 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보다 클 경우 2배 정밀도의 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,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비트가 할당됩니다.

Wikipedia에서 (자세한 내용은 여기를 참조하십시오)

IEEE 754 더블 부동 소수점 형식.

따라서 지수 부분을 2^52로 만들려면 e = 1075로 설정해야 합니다.

안전을 위해

var MAX_INT = 4294967295;

추리

가 그 수 것 .x + 1 === x아!

내 기계는 초당 천만 개 정도밖에 셀 수 없어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…(-1>>>0)

★★★★★★★★★★★★★★★(-(-1>>>1)-1)…(-1>>>1)

(비트 연산자와 배열의 최대 길이는 32비트 정수로 제한됩니다).

비트 연산자를 사용하지 않거나 배열 길이를 사용하지 않는 경우:

★★★★★★★★★★★★★★★(-Math.pow(2,53))…(+Math.pow(2,53))

이러한 제한은, 일반적으로 IEEE 754 의 배정도 부동 소수점 표현에 대응하는 「Number」타입의 내부 표현에 의해서 발생합니다.(일반 부호 정수와 달리 음의 한계 크기는 의 0을 포함하는 내부 표현의 특성 때문에 양의 한계 크기와 동일합니다.)

ECMAScript 6:

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

다른 사람들은 이미 일반적인 대답을 했을지도 모르지만, 나는 그것을 빨리 결정할 수 있는 좋은 생각이라고 생각했다.

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

따라서 Chrome 30에서는 1밀리초 이내에 9007199254740992를 사용할 수 있습니다.

2의 거듭제곱을 테스트하여 '1'이 추가되었을 때 자신과 동일한 것을 찾습니다.

비트 조작에 사용하는 것은 모두 0x80000000(-2147483648 또는 -2^31)에서 0x7ffff(2147483647 또는 2^31-1) 사이여야 합니다.

콘솔에 0x80000000은 +2147483648이지만 0x80000000과 0x80000000은 -2147483648이라고 표시됩니다.

2020에서 을 받았습니다.JavaScript ript ECMAScript 2020 。BigInt접미사가 "n"인 숫자 리터럴을 도입하여 임의의 정밀도를 가능하게 했다.

var a = 123456789012345678901012345678901n;

물론, 그러한 큰 정수가 (아마도) 숫자 데이터 타입에 강요되어도 정밀도는 여전히 손실됩니다.

그리고 당연히 한정된 메모리 때문에 항상 정밀도가 제한되고 필요한 메모리를 할당하고 그 큰 숫자에 대해 연산을 하기 위한 시간적인 비용이 발생합니다.

예를 들어, 10만 자리수의 숫자가 생성되면 완료되기 전에 상당한 지연이 발생합니다.

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

...하지만 그것은 효과가 있다.

시험:

maxInt = -1 >>> 1

파이어폭스 3.6에서는 2^31-1입니다.

X-(X+1)=-1이라는 공식으로 간단한 테스트를 수행했는데, Safari, Opera 및 Firefox(OS X에 포함)에서 작업할 수 있는 X의 최대값은 9e15입니다.테스트에 사용한 코드는 다음과 같습니다.

javascript: alert(9e15-(9e15+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;

출처를 알아보겠습니다.

묘사

MAX_SAFE_INTEGER은 수수 、 수 constant 、 을 constant constant constant constant 。9007199254740991(9,007,199,254,740,991 또는 ~9,000조).이 숫자의 배후에 있는 이유는 JavaScript가 IEEE 754에서 지정된 대로 2배 정밀도의 부동소수점 형식 번호를 사용하고 있으며 안전하게 표시할 수 있는 것은 다음 중 하나의 숫자뿐입니다.-(2^53 - 1) ★★★★★★★★★★★★★★★★★」2^53 - 1.

이 문맥에서 안전이란 정수를 정확하게 표현하고 정확하게 비교하는 능력을 말합니다.를 들어, 「」라고 하는 것은,Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2true로 평가하지만 수학적으로 올바르지 않습니다.Number.is Safe 참조자세한 내용은 Integer()참조하십시오.

★★★★★★★★★★★★★★★★★★MAX_SAFE_INTEGERNumber의 정적 속성입니다.항상 Number는 Number로 사용합니다.Number.MAX_SAFE_INTEGER작성한 Number 객체의 속성으로 하는 것이 아니라,

브라우저 호환성

여기에 이미지 설명 입력

은 JavaScript입니다.2^53 - 1.

, 는 에서 계산됩니다.즉, 32비트 시프트를 넘으면 비트 손실이 시작됩니다.

Google Chrome 내장 Javascript 에서는, 인피니티라고 불리기 전에 약 2^1024 로 이동할 수 있습니다.

Scato wrotes:

비트 조작에 사용하는 것은 모두 0x80000000(-2147483648 또는 -2^31)에서 0x7ffffff(2147483647 또는 2^31 - 1) 사이여야 합니다.

콘솔에는 0x80000000은 +2147483648이지만 0x80000000과 0x80000000은 -2147483648이라고 표시됩니다.

16진수는 부호 없는 양수 값이므로 0x80000000 = 2147483648 - 수학적으로 정확합니다.서명된 값으로 하려면 0x80000000 >> 0 = -2147483648을 오른쪽 이동해야 합니다.대신 1 < < 31 이라고 쓸 수도 있습니다.

파이어폭스3는 엄청난 숫자에 문제가 없는 것 같다.

1e+200 * 1e+100 은 1e+300 으로 계산됩니다.

Safari도 문제가 없는 것 같습니다.(공개를 위해 다른 사람이 테스트하면 Mac에 있습니다.)

이 시간에 뇌를 잃기 전까진 64비트 정수보다 훨씬 커요

Node.js와 Google Chrome은 모두 1024비트 부동소수점 값을 사용하는 것으로 보여집니다.

Number.MAX_VALUE = 1.7976931348623157e+308

언급URL : https://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin

반응형