Jaka jest najwyższa wartość całkowita JavaScript, do której liczba może przejść bez utraty precyzji?

951

Czy to określa język? Czy istnieje określone maksimum? Czy różni się w różnych przeglądarkach?

TALlama
źródło
5
Nie musisz polegać na limitach JS w bibliotekach takich jak github.com/MikeMcl/big.js , patrz np. Tutaj dla jego testów niezawodności
Dmitri Zaitsev
2
Jaka jest najwyższa wartość całkowita, której możesz użyć w big.js?
George
@George Oto interfejs API big.js: mikemcl.github.io/big.js/#dp
simhumileco
Pytanie nie ma sensu. Co to znaczy, że liczba „idzie” do wartości całkowitej? Jeśli chcesz tylko zapytać, jaka jest najwyższa liczba całkowita, którą możesz reprezentować w JS, sama najwyższa (skończona) liczba jest liczbą całkowitą.
Veky,
@DmitriZaitsev Nie musimy już polegać na bibliotekach zewnętrznych (przynajmniej w niektórych przeglądarkach). 1n << 10000njest naprawdę dużą liczbą całkowitą, bez utraty precyzji, bez żadnych zależności (i nie trzeba dodawać, nawet bliskie granicy).
Amadan

Odpowiedzi:

867

JavaScript ma dwa typy liczb: Numberi BigInt.

Najczęściej stosowanym typem liczby Numberjest 64-bitowa liczba zmiennoprzecinkowa IEEE 754 .

Największa dokładna całkowita wartość tego typu Number.MAX_SAFE_INTEGERto:

  • 2 53 -1 lub
  • +/- 9 007,199,254,740,991 lub
  • dziewięć bilionów siedem bilionów sto dziewięćdziesiąt dziewięć miliardów dwieście pięćdziesiąt cztery miliony siedemset czterdzieści tysięcy dziewięćset dziewięćdziesiąt jeden

Mówiąc inaczej: jeden kwadrylion bajtów to petabajt (lub tysiąc terabajtów).

„Bezpieczny” w tym kontekście odnosi się do możliwości dokładnego przedstawienia liczb całkowitych i ich prawidłowego porównania.

Ze specyfikacji:

Zauważ, że wszystkie dodatnie i ujemne liczby całkowite, których wielkość nie jest większa niż 2 53, są reprezentowalne w Numbertypie (w rzeczywistości liczba całkowita 0 ma dwie reprezentacje, +0 i -0).

Aby bezpiecznie używać liczb całkowitych większych niż to, musisz użyć BigInt, który nie ma górnej granicy.

Zauważ, że operatory bitowe i operatory shift działają na 32-bitowych liczbach całkowitych, więc w takim przypadku maksymalna bezpieczna liczba całkowita wynosi 2 31 -1 lub 2 147 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


Uwaga techniczna na temat liczby 9 007,199,254,740,992: Istnieje dokładna reprezentacja tej wartości według IEEE-754, i możesz przypisać i odczytać tę wartość ze zmiennej, więc dla bardzo starannie wybranych aplikacji w dziedzinie liczb całkowitych mniejszych lub równych tę wartość można traktować jako wartość maksymalną.

W ogólnym przypadku należy traktować tę wartość IEEE-754 jako niedokładną, ponieważ nie jest jednoznaczne, czy koduje ona wartość logiczną 9,007,199,254,740,992, czy 9 ​​007,199,25 940,993.

Jimmy
źródło
75
Wydaje się to słuszne, ale czy jest gdzieś to zdefiniowane, na przykład MAX_INT la C lub Integer Java.MAX_VALUE?
TALlama,
48
4294967295 === Math.pow(2,32) - 1;
CoolAJ86,
13
Jaka jest najmniejsza i największa liczba całkowita, której możemy użyć, aby zapewnić dokładność?
Pacerier
38
Być może warto zauważyć, że w javascript nie ma rzeczywistej (int). Każde wystąpienie liczby jest (zmiennoprzecinkowe) lub NaN.
Beetroot-Beetroot
53
9007199254740992 nie jest tak naprawdę wartością maksymalną, zakłada się, że ostatni bit tutaj wynosi zero, więc straciłeś 1 bit precyzji. Prawdziwy bezpieczny numer to 9007199254740991 (Number.MAX_SAFE_INTEGER)
Willem D'Haeseleer
461

> = ES6:

Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;

<= ES5

Z referencji :

Number.MAX_VALUE;
Number.MIN_VALUE;

Peter Bailey
źródło
23
Zredagowałem pytanie, aby być bardziej precyzyjnym w kwestii potrzeby maksymalnych wartości całkowitych, a nie tylko maksymalnej wartości liczbowej. Przepraszam za zamieszanie, tutaj.
TALlama,
5
Czy gwarantowany wynik jest taki sam we wszystkich przeglądarkach?
Pacerier
7
Zauważ, że Number.MIN_VALUEjest to najmniejsza możliwa liczba dodatnia . Prawdopodobnie jest to najmniejsza wartość (tj. Mniejsza niż cokolwiek innego) -Number.MAX_VALUE.
Michael Scheper,
34
ES6 wprowadza Number.MIN_SAFE_INTEGERiNumber.MAX_SAFE_INTEGER
superlukas
2
Czy w takim przypadku powinniśmy zagłosować na odpowiedź, ponieważ jest ona nieodpowiednia dla zaktualizowanego pytania, czy też zostawić ją, ponieważ Peter Baily miał rację w momencie udzielenia odpowiedzi?
rakiety są szybkie
112

Wynosi 2 53 == 9 007 199 254 740 992. Jest tak, ponieważ Numbers są przechowywane jako zmiennoprzecinkowe w 52-bitowej mantysie.

Minimalna wartość to -2 53 .

To sprawia, że ​​dzieją się fajne rzeczy

Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true

I może być również niebezpieczne :)

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
}

Dalsza lektura: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

Vjeux
źródło
1
choć nigdy nie dojdzie do końca pętli w rozsądnych ramach czasowych, możesz powiedzieći += 1000000000
ninjagecko
2
@ninjagecko, zaczyna on od MAX_INT, więc koniec jest właśnie tam. Również użycie i + = 1000000000 sprawi, że nie będzie to już nieskończona pętla. Spróbuj.
Ted Bigham
@TedBigham: Ach, ups, byłem przez to gotowy zbyt szybko. Dzięki za poprawienie mnie dwa razy.
ninjagecko
Zobacz argument Jimmy'ego za 9 007 199 254 440,991 zamiast 9 007 199,254,740,992 tutaj . To, w połączeniu z moimi działaniami następczymi, wydaje się przekonujące.
TJ Crowder
60

W JavaScript istnieje pewna liczba o nazwie Infinity.

Przykłady:

(Infinity>100)
=> true

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

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

Może to wystarczyć w przypadku niektórych pytań dotyczących tego tematu.

BananaNeil
źródło
25
Coś mi mówi, że nieskończoność nie kwalifikuje się jako liczba całkowita. :)
devios1,
7
Ale wystarczy zainicjować minzmienną, gdy szukasz wartości minimalnej.
djjeck
9
Zauważ, żeInfinity - 1 === Infinity
H.Wolper
2
również (Nieskończoność <100) => fałsz i Math.pow (2,1024) === Nieskończoność
Sijav
6
Również nic nie warte, że radzi sobie również z ujemną Nieskończonością. Więc1 - Infinity === -Infinity
dmccabe
41

Odpowiedź Jimmy'ego poprawnie reprezentuje ciągłe spektrum JavaScript jako -9007199254740992 do 9007199254740992 włącznie (przepraszam 9007199254740993, możesz pomyśleć, że masz 9007199254740993, ale się mylisz! Demonstracja poniżej lub w jsfiddle ).

console.log(9007199254740993);

Jednak nie ma odpowiedzi, która znalazłaby / udowodniłaby to programowo (inna niż ta, o której wspominał CoolAJ86 w swojej odpowiedzi , która skończyłaby się za 28,56 lat;), więc oto nieco bardziej skuteczny sposób na to (dokładniej mówiąc, jest bardziej wydajny o około 28,559999999968312 lat :), wraz ze skrzypką testową :

/**
 * 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
źródło
8
@ CoolAJ86: Lol, nie mogę się doczekać 15 marca 2040 r. Jeśli nasze liczby się zgadzają, powinniśmy zorganizować imprezę :)
Briguy37
var x = Math.pow (2,53) -3; while (x! = x + 1) x ++; -> 9007199254740991
MickLH
@MickLH: Otrzymuję 9007199254740992 z tym kodem . Jakiego silnika JavaScript używasz do testowania?
Briguy37,
Otrzymujesz 9007199254740992 ze swoim własnym kodem, nie użyłem końcowej wartości x, ale ostateczną wersję x ++ z powodów paranoicznych. Google Chrome btw.
MickLH,
@MickLH: ocena x++daje wartość x przed wystąpieniem przyrostu, więc prawdopodobnie wyjaśnia to rozbieżność. Jeśli chcesz, aby wyrażenie miało taką samą wartość jak końcowa wartość x, powinieneś to zmienić na ++x.
peterflynn
32

Być bezpiecznym

var MAX_INT = 4294967295;

Rozumowanie

Myślałem, że będę sprytny i znajdę wartość, za jaką x + 1 === x przyniesie bardziej pragmatyczne podejście.

Moja maszyna może liczyć tylko około 10 milionów na sekundę ... więc odpowiem z ostateczną odpowiedzią za 28,56 lat.

Jeśli nie możesz czekać tak długo, jestem gotów się założyć

  • Większość twoich pętli nie działa przez 28,56 lat
  • 9007199254740992 === Math.pow(2, 53) + 1 jest wystarczającym dowodem
  • Powinieneś trzymać się 4294967295tego, Math.pow(2,32) - 1aby uniknąć oczekiwanych problemów z przesuwaniem bitów

Znalezienie 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);
}());
CoolAJ86
źródło
4
nie możesz po prostu zacząć od 2 ^ 53 - 2, aby przetestować? (tak, mogę, właśnie wypróbowałem, nawet z -3, aby być bezpiecznym: var x = Math.pow (2,53) -3; while (x! = x + 1) x ++;) -> 9007199254740991
MickLH
Niezła odpowiedź! Co więcej, wiem, że wartość jest ustalona, ​​ale dlaczego nie użyć wyszukiwania binarnego do jej znalezienia?
higuaro,
1
Co w tym jest fajnego? Poza tym @ Briguy37 mnie pobił: stackoverflow.com/a/11639621/151312
CoolAJ86
zwróć uwagę, że ten „bezpieczny” MAX_INT oparty na 32 bitach nie będzie działał podczas porównywania z wartościami Daty. 4294967295 jest taki wczoraj!
Jerry,
1
Odpowiedź „Aby być bezpiecznym: var MAX_INT = 4294967295;” nie jest zabawny. Jeśli nie przesuwasz bitów, nie przejmuj się tym (chyba że potrzebujesz int większej niż 4294967295, w którym to przypadku prawdopodobnie powinieneś zapisać go jako ciąg i użyć biblioteki bigint).
CoolAJ86,
29

Krótka odpowiedź brzmi „to zależy”.

Jeśli używasz operatorów bitowych w dowolnym miejscu (lub jeśli odwołujesz się do długości tablicy), zakresy są następujące:

Bez podpisu: 0…(-1>>>0)

Podpisano: (-(-1>>>1)-1)…(-1>>>1)

(Zdarza się, że operatory bitowe i maksymalna długość tablicy są ograniczone do 32-bitowych liczb całkowitych.)

Jeśli nie używasz operatorów bitowych lub pracujesz z długością tablicy:

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

Ograniczenia te są narzucone przez wewnętrzną reprezentację typu „Liczba”, która zasadniczo odpowiada reprezentacji zmiennoprzecinkowej podwójnej precyzji IEEE 754. (Należy zauważyć, że w przeciwieństwie do typowych liczb całkowitych ze znakiem, wielkość limitu ujemnego jest taka sama jak wielkość limitu dodatniego, ze względu na cechy reprezentacji wewnętrznej, która w rzeczywistości zawiera ujemną wartość 0!)

Danorton
źródło
Oto odpowiedź, na którą chciałem się natknąć, jak przekonwertować X na 32-bitową liczbę całkowitą lub liczbę całkowitą bez znaku. Poparłem za to twoją odpowiedź.
Charlie Affumigato
29

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
WaiKit Kung
źródło
1
Uwaga, nie jest to (jeszcze) obsługiwane przez wszystkie przeglądarki! Dzisiaj iOS (nawet Chrome), Safari i IE tego nie lubią.
cregox
5
Przeczytaj uważnie odpowiedź, nie używamy domyślnej implementacji Number.MAX_SAFE_INTEGER w ECMAScript 6, definiujemy ją przez Math.pow (2, 53) -1
WaiKit Kung
Myślałem, że to tylko odniesienie do tego, jak jest on zaimplementowany w ECMA 6! : PI sądzę jednak, że mój komentarz jest nadal aktualny. Wszystko zależy od kontekstu. ;)
cregox
3
Czy obliczenie MAX_SAFE_INTEGERwe wszystkich przeglądarkach jest niezawodne, jeśli pracujesz wstecz? Czy zamiast tego powinieneś iść do przodu? Tj. Number.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) + 1;
kjv
Czy Math.pow(2, 53)-1bezpieczna jest operacja? Jest większa niż największa bezpieczna liczba całkowita.
ioquatix
21

Wiele odpowiedzi od wcześniej wykazały wynik truew 9007199254740992 === 9007199254740992 + 1celu sprawdzenia, 9 007 199 254 740 991 to maksymalna liczba całkowita i bezpieczna.

Co się stanie, jeśli będziemy kontynuować gromadzenie:

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

Możemy dowiedzieć się, że wśród liczb większych niż 9 007 199 254 740 992 tylko liczby parzyste są reprezentowalne .

Jest to wejście, aby wyjaśnić, w jaki sposób działa na tym 64-bitowy format podwójnej precyzji . Zobaczmy, jak 9 007 199 254 740 992 może być przechowywany (reprezentowany) przy użyciu tego formatu binarnego.

Używanie krótkiej wersji, aby to zademonstrować 4 503 599 627 370 496 :

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

Po lewej stronie strzałki mamy wartość bitu 1 i sąsiedni punkt podstawy , a następnie pomnożąc 2^52, przesuwamy punkt podstawy o 52 kroki i idzie do końca. Teraz otrzymujemy 4503599627370496 w postaci binarnej.

Teraz zaczynamy kumulować 1 do tej wartości, aż wszystkie bity zostaną ustawione na 1, co jest równe 9 007 199 254 740 991 dziesiętnie.

  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. 

Teraz, ponieważ to w 64-bitowym formacie binarnym o podwójnej precyzji przydziela ułamek 52 bitów, ułamek nie jest już dostępny do dodania 1, więc możemy ustawić wszystkie bity z powrotem na 0 i manipuluj częścią wykładniczą:

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

Teraz otrzymujemy 9 007 199 254 740 992 , a przy większej liczbie format może pomieścić 2 razy część ułamka , co oznacza, że ​​teraz 1 dodanie części ułamkowej faktycznie równa się 2 dodatkom, dlatego podwójne -precision 64-bitowy format binarny nie może przechowywać liczb nieparzystych, gdy liczba jest większa niż 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 --|

Tak więc, gdy liczba osiągnie więcej niż 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, tylko 4 razy ułamek może być utrzymany:

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

Co powiesz na liczbę między [ 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  --|

Wartość bitu 1 po punkcie radix wynosi dokładnie 2 ^ -1. (= 1/2, = 0,5) Więc jeśli liczba jest mniejsza niż 4 503 599 627 370 496 (2 ^ 52), dostępny jest jeden bit reprezentujący 1/2 razy liczby całkowitej :

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

Mniej niż 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"

Jaki jest dostępny zakres części wykładniczej ? format przydziela mu 11 bitów. Pełny format z Wiki : (Aby uzyskać więcej informacji, przejdź tam)

Format IEEE 754 Double Floating Point Format.svg

wprowadź opis zdjęcia tutaj

Aby więc część wykładnicza wynosiła 2 ^ 52, musimy dokładnie ustawić e = 1075.

Carr
źródło
13

Inni mogli już udzielić ogólnej odpowiedzi, ale pomyślałem, że dobrym pomysłem byłoby podanie szybkiego sposobu jej ustalenia:

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

Co daje mi 9007199254740992 w mniej niż milisekundę w Chrome 30.

Testuje moc 2, aby znaleźć, która z „dodanych” 1 równa się sobie.

Philippe97
źródło
Może to spowodować awarię aplikacji, pomyślał.
Sapphire_Brick
8

Wszystko, czego chcesz użyć do operacji bitowych, musi znajdować się między 0x80000000 (-2147483648 lub -2 ^ 31) a 0x7fffffff (2147483647 lub 2 ^ 31-1).

Konsola powie ci, że 0x80000000 równa się +2147483648, ale 0x80000000 i 0x80000000 wynosi -2147483648.

Scato
źródło
6

Próbować:

maxInt = -1 >>> 1

W Firefoksie 3.6 jest to 2 ^ 31 - 1.

Martin Naatz
źródło
2
@danorton: Nie jestem pewien, czy rozumiesz, co robisz. ^oznacza podniesione do władzy . W konsoli javascript ^jest XOR , nie podniesiony do
kumarharsh
2
otwórz konsolę Chrome / Firefox. Wpisz 5 ^ 2. W systemie binarnym 5 to, 101a 2 to 010. Teraz, jeśli bitorujesz je XOR, otrzymasz 5(101) ^ 2(010) = 7(111) CZYTAJ TO, JEŚLI JESTEŚ ZAUFANY To, o czym tutaj dyskutujemy, Math.pow()nie jest ^operatorem
kumarharsh
3
Znów nie jestem wcale zdezorientowany. Skomentowałem i przegłosowałem to, co jest napisane . Jeśli chodzi o Math.pow (), to należy to napisać. W odpowiedzi na pytanie dotyczące JavaScript niewłaściwe jest używanie składni innego języka. Jeszcze bardziej niewłaściwe jest stosowanie składni poprawnej w JavaScript, ale z interpretacją w JavaScript, która ma inne znaczenie niż to, co jest zamierzone.
danorton
10
2 ^ 31 to sposób, w jaki pisze się dwa do trzydziestej pierwszej potęgi w języku angielskim. Nie ma go w bloku kodu. Czy narzekałbyś na kogoś, kto używa; w odpowiedzi, ponieważ jest to znak o innym znaczeniu w JavaScript?
lmm
3
Chociaż należy pisać 2³¹, a nie 2 ^ 31 zwykłym tekstem, często się to robi, ponieważ większość układów klawiatury domyślnie nie ma tych znaków. Przynajmniej nie miałem żadnych problemów ze zrozumieniem, co miał na myśli ta odpowiedź.
Jocke
6

W momencie pisania, JavaScript odbiera nowy typ danych: BigInt. Jest to propozycja TC39 na etapie 4, która ma zostać uwzględniona w EcmaScript 2020 . BigIntjest dostępny w Chrome 67+, FireFox 68+, Opera 54 i Node 10.4.0. Jest w toku w Safari i in. ... Wprowadza literały liczbowe z sufiksem „n” i pozwala na dowolną precyzję:

var a = 123456789012345678901012345678901n;

Precyzja nadal będzie oczywiście utracona, gdy taka liczba zostanie (być może nieumyślnie) wymuszona na typ danych liczbowych.

I oczywiście zawsze będą istnieć ograniczenia precyzji ze względu na skończoną pamięć i koszt pod względem czasu, aby przydzielić niezbędną pamięć i wykonać arytmetykę na tak dużych liczbach.

Na przykład generowanie liczby o stu tysiącach cyfr dziesiętnych zajmie zauważalne opóźnienie przed ukończeniem:

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

... ale to działa.

trincot
źródło
4

Zrobiłem prosty test z formułą, X- (X + 1) = - 1, a największa wartość XI, jaką można uzyskać w przeglądarce Safari, Opera i Firefox (testowana w systemie OS X), to 9e15. Oto kod, którego użyłem do testowania:

javascript: alert(9e15-(9e15+1));
Raynet
źródło
1
Zauważ, że 9e15 = 2 ^ 53 (patrz odpowiedź @ Jimmy'ego).
Wedge
6
9e15 = 9000000000000000. 2 ^ 53 = 9007199254740992. Dlatego, aby być pedantycznym, 9e15 jest tylko w przybliżeniu równy 2 ^ 53 (z dwiema cyframi znaczącymi).
devios1
@chaiguy 9000000000000000Jest 1 znacząca liczba. w `9007199254740992` jest 15 znaczących liczb.
Royi Namir
@RoyiNamir Nie chcę tutaj zaczynać bezcelowego argumentu, ale 9000000000000000 ma 16 cyfr znaczących. Jeśli chcesz tylko 1, trzeba go zapisać jako 9x10 ^ 15.
devios1
1
@chaiguy Nie, 9000000000000000jak jest - ma 1SF. gdzie 90*10^14ma 2. ( sigfigscalculator.appspot.com ) i mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (dolna część)
Royi Namir
3

Piszę tak:

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

To samo dla int32

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;
jerome
źródło
3

Przejdźmy do źródeł

Opis

MAX_SAFE_INTEGERStała ma wartość 9007199254740991(9.007.199.254.740.991 kwadrylion lub ~ 9). Powodem tej liczby jest to, że JavaScript używa liczb zmiennoprzecinkowych o podwójnej precyzji określonych w IEEE 754 i może tylko bezpiecznie reprezentować liczby między -(2^53 - 1)i2^53 - 1 .

Bezpieczny w tym kontekście odnosi się do możliwości dokładnego przedstawienia liczb całkowitych i ich prawidłowego porównania. Na przykład Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2oceni na true, co jest matematycznie niepoprawne. Aby uzyskać więcej informacji, zobacz Number.isSafeInteger () .

Ponieważ MAX_SAFE_INTEGERjest to statyczna właściwość Number , zawsze używasz jej jako Number.MAX_SAFE_INTEGER, a nie jako właściwości utworzonego obiektu Number .

Kompatybilność z przeglądarkami

wprowadź opis zdjęcia tutaj

simhumileco
źródło
-1

Wato Scato:

wszystko, czego chcesz użyć do operacji bitowych, musi znajdować się między 0x80000000 (-2147483648 lub -2 ^ 31) a 0x7fffffff (2147483647 lub 2 ^ 31-1).

konsola powie ci, że 0x80000000 wynosi +2147483648, ale 0x80000000 i 0x80000000 wynosi -2147483648

Szesnastkowe są dodatnimi wartościami bez znaku, więc 0x80000000 = 2147483648 - to matematycznie poprawne. Jeśli chcesz, aby była to podpisana wartość, musisz przesunąć w prawo: 0x80000000 >> 0 = -2147483648. Możesz też napisać 1 << 31.

SammieFox
źródło
-7

Firefox 3 nie wydaje się mieć problemu z dużymi liczbami.

1e + 200 * 1e + 100 obliczy grzywnę do 1e + 300.

Wygląda na to, że Safari również nie ma z tym problemu. (Dla przypomnienia, jest to na komputerze Mac, jeśli ktoś zdecyduje się to przetestować).

O ile nie straciłem mózgu o tej porze dnia, jest to znacznie więcej niż 64-bitowa liczba całkowita.

jishi
źródło
18
nie jest to 64-bitowa liczba całkowita, to 64-bitowa liczba zmiennoprzecinkowa, z czego 52/53 bity są liczbą całkowitą. więc poradzi sobie do 1e300, ale nie z dokładną precyzją.
Jimmy
4
Jimmy ma rację. Spróbuj tego w przeglądarce lub wierszu polecenia JS:100000000000000010 - 1 => 100000000000000020
Ryan,
-7

Wydaje się, że Node.js i Google Chrome używają 1024-bitowych wartości zmiennoprzecinkowych, więc:

Number.MAX_VALUE = 1.7976931348623157e+308
TinyTimZamboni
źródło
1
-1: maksymalna reprezentowalna (nieprecyzyjna liczba całkowita) może wynosić ~ 2 ^ 1024, ale to nie znaczy, że odbiegają one od standardu 64- bitowego IEEE-754 .
Roy Tinker,
2
MAX_INT? Masz na myśli MAX_VALUE?
Raul Guiu
3
to maksimum wartości zmiennoprzecinkowej . Nie oznacza to, że możesz przechowywać int tak długo
phuclv
1
Lub bardziej konkretnie , nie można niezawodnie przechowywać int tak długo bez utraty dokładności . 2^53określa się jako, MAX_SAFE_INTponieważ powyżej tego punktu wartości stają się przybliżeniami, podobnie jak ułamki.
IMSoP