Czy to określa język? Czy istnieje określone maksimum? Czy różni się w różnych przeglądarkach?
1n << 10000n
jest naprawdę dużą liczbą całkowitą, bez utraty precyzji, bez żadnych zależności (i nie trzeba dodawać, nawet bliskie granicy).
Czy to określa język? Czy istnieje określone maksimum? Czy różni się w różnych przeglądarkach?
1n << 10000n
jest naprawdę dużą liczbą całkowitą, bez utraty precyzji, bez żadnych zależności (i nie trzeba dodawać, nawet bliskie granicy).
Odpowiedzi:
JavaScript ma dwa typy liczb: Number
i BigInt
.
Najczęściej stosowanym typem liczby Number
jest 64-bitowa liczba zmiennoprzecinkowa IEEE 754 .
Największa dokładna całkowita wartość tego typu Number.MAX_SAFE_INTEGER
to:
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.
Zauważ, że wszystkie dodatnie i ujemne liczby całkowite, których wielkość nie jest większa niż 2 53, są reprezentowalne w
Number
typie (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.
4294967295 === Math.pow(2,32) - 1;
> = ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
<= ES5
Z referencji :
Number.MAX_VALUE;
Number.MIN_VALUE;
Number.MIN_VALUE
jest to najmniejsza możliwa liczba dodatnia . Prawdopodobnie jest to najmniejsza wartość (tj. Mniejsza niż cokolwiek innego) -Number.MAX_VALUE
.
Number.MIN_SAFE_INTEGER
iNumber.MAX_SAFE_INTEGER
Wynosi 2 53 == 9 007 199 254 740 992. Jest tak, ponieważ Number
s 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
i += 1000000000
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.
min
zmienną, gdy szukasz wartości minimalnej.
Infinity - 1 === Infinity
1 - Infinity === -Infinity
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);
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
.
var MAX_INT = 4294967295;
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ć
9007199254740992 === Math.pow(2, 53) + 1
jest wystarczającym dowodem4294967295
tego, Math.pow(2,32) - 1
aby uniknąć oczekiwanych problemów z przesuwaniem bitówZnalezienie 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);
}());
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!)
ECMAScript 6:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
MAX_SAFE_INTEGER
we 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;
Math.pow(2, 53)-1
bezpieczna jest operacja? Jest większa niż największa bezpieczna liczba całkowita.
Wiele odpowiedzi od wcześniej wykazały wynik true
w 9007199254740992 === 9007199254740992 + 1
celu 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)
Aby więc część wykładnicza wynosiła 2 ^ 52, musimy dokładnie ustawić e = 1075.
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.
Próbować:
maxInt = -1 >>> 1
W Firefoksie 3.6 jest to 2 ^ 31 - 1.
^
oznacza podniesione do władzy . W konsoli javascript ^
jest XOR , nie podniesiony do
101
a 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
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 . BigInt
jest 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.
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));
9000000000000000
Jest 1 znacząca liczba. w `9007199254740992` jest 15 znaczących liczb.
9000000000000000
jak jest - ma 1
SF. gdzie 90*10^14
ma 2. ( sigfigscalculator.appspot.com ) i mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (dolna część)
MAX_SAFE_INTEGER
Stał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 + 2
oceni na true, co jest matematycznie niepoprawne. Aby uzyskać więcej informacji, zobacz Number.isSafeInteger () .Ponieważ
MAX_SAFE_INTEGER
jest to statyczna właściwość Number , zawsze używasz jej jakoNumber.MAX_SAFE_INTEGER
, a nie jako właściwości utworzonego obiektu Number .
We wbudowanym javascript w Google Chrome możesz przejść do około 2 ^ 1024, zanim numer nazywa się nieskończonością.
W JavaScript reprezentacja liczb to 2^53 - 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.
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.
100000000000000010 - 1 => 100000000000000020
Wydaje się, że Node.js i Google Chrome używają 1024-bitowych wartości zmiennoprzecinkowych, więc:
Number.MAX_VALUE = 1.7976931348623157e+308
2^53
określa się jako, MAX_SAFE_INT
ponieważ powyżej tego punktu wartości stają się przybliżeniami, podobnie jak ułamki.