Natknąłem się na ten problem chwilę, kiedy testowałem kilka formularzy HTML. Maksymalna liczba cyfr w numerze JavaScript z punktem dziesiętnym wynosi tylko 16

Wypróbowałem następujące

var x = 12345678912345.6789

X wynosi 12345678912345.68 - Tylko 16 cyfr

var x = 123456789123.6789

X wynosi 123456789123.6789 - Tylko 16 cyfr

new Number(12345678912345.6789)

12345678912345.68 - Tylko 16 cyfr

new Number(123456789123.6789)

123456789123.6789 - Tylko 16 cyfr

Jeśli policzysz całkowitą cyfry, są 16. Jeśli zwiększysz cyfry przed dziesiętnym punktem, cyfry po dziesiętnym punkcie zostaną zaokrąglone

Podobnie

new Number(.12345678912367890)

Wynosi 0,1234567891236789 - tylko 16 cyfr Tylko (brakuje końca 0

Co sprawia, że dedukę, że mogę mieć tylko 16 cyfr w liczbie z dziesiętną w nim. Jeśli spróbuję dodać więcej cyfr, liczba zaczyna się

Zauważyłem też, że kiedy serializuję liczbę z dziesiętną w JSON w ASP.NET MVC, konwertuje numer do max 16 cyfr i zaokrąglenia reszta

Moje pytanie: dlaczego?

4
U.P 21 luty 2019, 08:44

2 odpowiedzi

Najlepsza odpowiedź

Według specyfikacji JS / ECMAScript, Number typ korzysta z podwójnego precyzyjnego punktu zmiennego, który ma 64-bitowy format (binary64), składa się z bitów znakowych (określa wartość dodatnią lub ujemną), 11 bitów wykładników i 52 bitów frakcji (każda cyfra reprezentuje 4- Bity, stąd 64-bit ma 16 cyfr):

Typ liczby reprezentujący format 64-bitowy IEEE 754-2008 Wartości , jak określono w normie IEEE dla binarnego Arytmetyka pływające.

Maksymalna liczba dodatnia, która może być prawidłowo reprezentowana przy użyciu podwójnej precyzji jest 9007199254740992, który można osiągnąć za pomocą Math.pow(2, 53). Jeśli zakres liczby znajduje się między Math.pow(2, 53) i Math.pow(2, 54) (lub między Math.pow(2, -53) i Math.pow(2, -54)), tylko numery nawet mogą być prawidłowo reprezentowane, ponieważ bitów wykładniały wpłyną na LSB (przynajmniej znaczący bit) na bitach frakcji.

Przejrzyjmy część dużej liczby:

var x = 12345678912345.6789

var x = new Number(12345678912345.6789)

Ta liczba zawiera więcej niż 52 bitów frakcyjnych (łącznie 72 bitów), stąd zaokrąglanie używany do przechowywania frakcyjnych bitów do 52.

Również dzięki tej liczbie dziesiętnej:

var x = new Number(.12345678912367890)

Ta liczba zawiera 68 frakcyjnych bitów, stąd ostatnie zero jest wyłączone, aby utrzymać 64-bitową długość.

Zwykle reprezentacja numeryczna większa niż 9007199254740992 lub mniejsza niż 1.1102230246251565E-16 są przechowywane jako dosłowne struny zamiast Number. Jeśli potrzebujesz obliczyć bardzo duże liczby, dostępne są pewne biblioteki zewnętrzne do wykonania arbitralnego precyzyjnego arytmetycznego.

Czytaj dalej:

ECMASCRIPT: Numer kodujący

ECMASCRIPT: Praca z dużymi liczbami całkowitymi

5
Tetsuya Yamamoto 21 luty 2019, 09:14

W JavaScript, nie możesz reprezentować większości ułamków dziesiętnych dokładnie z binarnymi typami pływających punktów (co właśnie wykorzystuje ECMAScript, aby reprezentować wartość zmiennoprzecinkową).

Dlatego JavaScript wykorzystuje 16 liczb po punkcie dziesiętnym. na przykład -

Spróbuj biec:

var x =  3.14159265358979323846;
print(x.toFixed(20));

I zobacz, że obsada poniższa jest float.

Jeśli chcesz rzucić więcej niż 16 punktów po przecinku, możesz albo:

  • Użyj dosłownego ciągu, aby reprezentować swój numer
  • Użyj bibliotek zewnętrznych takich jak math.js lub Biginteger.js.
1
Barr J 21 luty 2019, 06:08