2016-09-06 15 views
13

Czytam książkę Douglasa Crockforda za - Javascript dobre części - i mówi:Jak jest mały przepełnienia całkowitą unikać JavaScript

JavaScript ma jeden typ numeru. Wewnętrznie jest reprezentowany jako 64-bitowy zmiennoprzecinkowy, taki sam jak podwójny Java. W przeciwieństwie do większości innych języków programowania, nie ma oddzielnego typu integer, więc 1 i 1.0 mają tę samą wartość. Jest to istotna wygoda, ponieważ całkowicie unika się problemów z przepełnieniem w krótkich liczbach całkowitych ...

Nie jestem zbyt zaznajomiony z innymi językami, więc chciałbym trochę wyjaśnienia. Rozumiem, dlaczego 64-bitowy pomaga, ale jego stwierdzenie zdaje się dotyczyć braku pływaków i podwójnych.

Jaki byłby (prawdopodobnie pseudo-kod) przykład krótkiej przepełnienia liczby całkowitej, która nie wystąpi w JS?

+1

całkowitymi w JS może być z - (2^53 - 1) do (2^53 - 1) .. skutecznie podpisany 54bit integer (ale nie całkiem, ale to nie ma znaczenia) ... krótkie liczby całkowite to 16bit ... 54 bitów jest większe niż 16 bitów ... więc nie ma problemów z przepełnieniem –

+0

przykład dla krótkich podpisów ... 32767 + 1 to 32768 w JS, w innych językach to -32768 –

+0

@JaromandaX ... powinno to być '- (2^53 + 1)'? Nie wiem ... po prostu ciekawy. – rnevius

Odpowiedz

8

Załóżmy, że masz 8-bitowy niepodpisany numer.

Oto wybór cyfrowych reprezentacji i binarne:

2: 00000010

15: 00001111

255: 11111111

Jeśli masz 255 i dodajesz 1, co się dzieje? Nie ma więcej bitów, więc otacza się

0: 00000000

Oto demonstracja w C# za pomocą uint (bez znaku 32-bitowa liczba całkowita) Wyjście

using System; 

public class Program 
{ 
    public static void Main() 
    { 
     uint n = 4294967294; 
     for(int i = 0; i < 4; ++i) 
     { 
      n = n + 1; 
      Console.WriteLine("n = {0}", n); 
     } 

    } 
} 

Ta wola :

n = 4294967294 
n = 4294967295 
n = 0 
n = 1 

Jest to problem, którego nie można uzyskać w javascript.


Otrzymujesz różne problemy.

Na przykład:

var n = 9007199254740991; 
 
var m = n + 1; 
 
var p = m + 1; 
 
alert('n = ' + n + ' and m = ' + m + ' and p = ' + p);

zostanie patrz

n = 9007199254740991 M = 9007199254740992, a p = 9007199254740992

Zamiast pak Wokół, twoje reprezentacje liczbowe stracą dokładność.


Zauważ, że ten „rzuca dokładność” zachowanie nie jest przypisany do javascript, to czego można oczekiwać od typów danych zmiennoprzecinkowych. Innym przykładem NET:

using System; 

public class Program 
{ 
    public static void Main() 
    { 
     float n = 16777214; // 2^24 - 2 
     for(int i = 0; i < 4; ++i) 
     { 
      Console.WriteLine(string.Format("n = {0}", n.ToString("0"))); 
      Console.WriteLine("(n+1) - n = {0}", (n+1)-n); 
      n = n + 1;     
     } 
    } 
} 

Wyjście będzie:

n = 16777210 
(n+1) - n = 1 
n = 16777220 
(n+1) - n = 1 
n = 16777220 
(n+1) - n = 0 
n = 16777220 
(n+1) - n = 0 
Powiązane problemy