program story

숫자가 정밀도를 잃지 않고 갈 수있는 JavaScript의 가장 높은 정수 값은 무엇입니까?

inputbox 2020. 9. 28. 09:05
반응형

숫자가 정밀도를 잃지 않고 갈 수있는 JavaScript의 가장 높은 정수 값은 무엇입니까?


이것은 언어에 의해 정의됩니까? 정의 된 최대 값이 있습니까? 브라우저마다 다르나요?


+/- 9007199254740991

ECMA 섹션 8.5-숫자

크기가 2 53 보다 크지 않은 모든 양의 정수와 음의 정수 는 숫자 유형으로 나타낼 수 있습니다 (실제로 정수 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을 인코딩하는지 여부가 모호하기 때문에 정확하지 않은 것으로 처리해야합니다.


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


이는 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


JavaScript에는 Infinity.

예 :

(Infinity>100)
=> true

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

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

이 주제와 관련된 몇 가지 질문에 충분할 수 있습니다.


Jimmy의 대답 은 연속 JavaScript 정수 스펙트럼을 -9007199254740992 ~ 9007199254740992 포함 으로 올바르게 나타냅니다 (죄송합니다 9007199254740993, 당신이 9007199254740993이라고 생각할 수도 있지만 틀 렸습니다! 아래 또는 jsfiddle의 데모 ).

document.write(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);


안전하다

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

ECMAScript 6 :

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

짧은 대답은 "상황에 따라 다릅니다."입니다.

어디에서나 비트 연산자를 사용하는 경우 (또는 배열의 길이를 참조하는 경우) 범위는 다음과 같습니다.

서명되지 않음 : 0…(-1>>>0)

서명 : (-(-1>>>1)-1)…(-1>>>1)

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

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

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

이러한 제한은 일반적으로 IEEE 754 배정 밀도 부동 소수점 표현에 해당하는 "숫자"유형의 내부 표현에 의해 부과됩니다. (일반적인 부호있는 정수와 달리 음의 한계의 크기는 실제로 음의 0을 포함하는 내부 표현의 특성으로 인해 양의 한계의 크기와 동일합니다 !)


이전의 많은 답변 9 007 199 254 740 991 이 최대 안전 정수인지 확인한 결과 true보여줍니다 .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가 어떻게 유지 (표현) 되는지 살펴 보겠습니다 .

먼저 4503 599 627370 496 에서 간단한 형식의 형식으로 시작합니다.

  1 . 0000 ---- 0000  *  2^52            =>  1  0000 ---- 0000.  
     |-- 52 bits --|    |exponent part|        |-- 52 bits --|

화살표 앞쪽에는 비트 값 1 과 인접한 기수 점이 있습니다 . 그런 다음 곱하여 2^52기수 점을 52 단계 오른쪽으로 이동하고 끝으로 이동합니다. 이제 우리는 바이너리로 4503599627370496을 얻습니다.

이제 모든 비트가 1로 설정 될 때까지이 값에 1을 누적하기 시작합니다 . 이는 10 진수로 9007 199254740 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 --| 

Now we get the 9 007 199 254 740 992, and with number greater than it, what the format could hold is 2 times of the fraction, it means now every 1 addition on the fraction part actually equals to 2 addition, that's why double-precision 64-bit binary format cannot hold odd numbers when number is greater than 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 --|

So when the number get to greater than 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, only 4 times of the fraction could be held:

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

How about number between [ 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  --|

The bit value 1 after radix point is 2^-1 exactly. (=1/2, =0.5) So when the number less than 4 503 599 627 370 496 (2^52), there is one bit available to represent the 1/2 times of the integer:

input: 4503599627370495.5   output: 4503599627370495.5  
input: 4503599627370495.75  output: 4503599627370495.5  

Less than 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"

And what is the available range of exponent part? the format allots 11 bits for it. Complete format from Wiki: (For more details please go there)

IEEE 754 Double Floating Point Format.svg

enter image description here

So to make exponent part be 2^52, we exactly need to set e = 1075.


Other may have already given the generic answer, but I thought it would be a good idea to give a fast way of determining it :

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

Which gives me 9007199254740992 within less than a millisecond in Chrome 30.

It will test powers of 2 to find which one, when 'added' 1, equals himself.


Anything you want to use for bitwise operations must be between 0x80000000 (-2147483648 or -2^31) and 0x7fffffff (2147483647 or 2^31 - 1).

The console will tell you that 0x80000000 equals +2147483648, but 0x80000000 & 0x80000000 equals -2147483648.


Try:

maxInt = -1 >>> 1

In Firefox 3.6 it's 2^31 - 1.


I did a simple test with a formula, X-(X+1)=-1, and the largest value of X I can get to work on Safari, Opera and Firefox (tested on OS X) is 9e15. Here is the code I used for testing:

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

At the moment of writing, JavaScript is receiving a new data type: BigInt. It is a TC39 proposal at stage 3. BigInt is available in Chrome 67+, FireFox 67+ (needs an option to activate it), Opera 54 and Node 10.4.0. It is underway in Safari, et al... It introduces numerical literals having an "n" suffix and allows for arbitrary precision:

var a = 123456789012345678901012345678901n;

Precision will still be lost, of course, when such a number is (maybe unintentionally) coerced to a number data type.


Let's get to the sources

Description

The MAX_SAFE_INTEGER constant has a value of 9007199254740991 (9,007,199,254,740,991 or ~9 quadrillion). The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between -(2^53 - 1) and 2^53 - 1.

Safe in this context refers to the ability to represent integers exactly and to correctly compare them. For example, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 will evaluate to true, which is mathematically incorrect. See Number.isSafeInteger() for more information.

Because MAX_SAFE_INTEGER is a static property of Number, you always use it as Number.MAX_SAFE_INTEGER, rather than as a property of a Number object you created.

Browser compatibility

enter image description here


In the Google Chrome built-in javascript, you can go to approximately 2^1024 before the number is called infinity.


I write it like this:

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

Same for int32

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;

Scato wrotes:

anything you want to use for bitwise operations must be between 0x80000000 (-2147483648 or -2^31) and 0x7fffffff (2147483647 or 2^31 - 1).

the console will tell you that 0x80000000 equals +2147483648, but 0x80000000 & 0x80000000 equals -2147483648

Hex-Decimals are unsigned positive values, so 0x80000000 = 2147483648 - thats mathematically correct. If you want to make it a signed value you have to right shift: 0x80000000 >> 0 = -2147483648. You can write 1 << 31 instead, too.


Number.MAX_VALUE represents the maximum numeric value representable in JavaScript.

Since no one seems to have said so, in the v8 engine there is a difference in behavior for 31 bits number and number above that.

If you have 32 bits you can use the first bit to tell the javascript engine what type that data is and have the remaining bits contain the actual data. That's what V8 does as a small optimisation for 31 bis numbers (or used to do, my sources are quite dated). You have the last 31 bits being the number value and then the first bit telling the engine if it's a number or an object reference.

However if you use number above 31 bits then the data won't fit in, the number will be boxed in 64 bits double and the optimisation won't be there.

The Bottom line, in the video below, is:

prefer numeric values that can be represented as 31bits signed integers.


Basically javascript doesn't support long.
so for normal values that it can represent less then 32 bit, it will use the int type container. for integer values greater then 32 bit its uses double. In double represntation the integer part is 53 bit and rest is mantissa( to keep floating point information).
so You can use 2^53 - 1 which value is 9007199254740991
you can access the value to use in your code by Number.MAX_SAFE_INTEGER


In JavaScript the representation of numbers is 2^53 - 1.

However, Bitwise operation are calculated on 32 bits ( 4 bytes ), meaning if you exceed 32bits shifts you will start loosing bits.


When the number is greater than 2 to the power 53 ie.

Math.pow(2, 53)

The javascript knows it as a big integer. Then javascript stores them as 'bigint' so comparing to 'bigint'==='bigint' becomes true.

Safer way to store their values in Math object itself.

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

Node.js and Google Chrome seem to both be using 1024 bit floating point values so:

Number.MAX_VALUE = 1.7976931348623157e+308

Firefox 3 doesn't seem to have a problem with huge numbers.

1e+200 * 1e+100 will calculate fine to 1e+300.

Safari seem to have no problem with it as well. (For the record, this is on a Mac if anyone else decides to test this.)

Unless I lost my brain at this time of day, this is way bigger than a 64-bit integer.

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

반응형