2016-09-06 45 views
13

Tôi đang đọc cuốn sách của Douglas Crockford - Javascript những phần tốt - và ông nói:thế nào là nhỏ tràn số nguyên tránh trong Javascript

JavaScript có một kiểu số duy nhất. Bên trong, nó được biểu diễn dưới dạng dấu phẩy động 64-bit, giống như dấu chấm kép của Java. Không giống như hầu hết các ngôn ngữ lập trình khác, không có loại số nguyên riêng biệt, vì vậy 1 và 1.0 có cùng giá trị. Đây là một sự thuận tiện đáng kể vì các vấn đề về tràn trong các số nguyên ngắn hoàn toàn tránh được ...

Tôi không quá quen thuộc với các ngôn ngữ khác để giải thích một chút. Tôi có thể hiểu lý do tại sao một chút 64 giúp nhưng tuyên bố của ông dường như áp dụng cho việc thiếu nổi và tăng gấp đôi.

Điều gì sẽ là (giả mã có lẽ) một ví dụ về tình huống tràn số nguyên ngắn sẽ không xảy ra trong JS?

+1

số nguyên trong JS có thể từ - (2^53-1) đến (2^53-1) .. có hiệu quả một 54bit ký số nguyên (nhưng không hoàn toàn thực sự, nhưng đó không phải là có liên quan) ... số nguyên ngắn là 16bit ... 54bits lớn hơn 16bits ... do đó không có vấn đề tràn –

+0

ví dụ cho chữ ký ngắn ... 32767 + 1 là 32768 trong JS, bằng các ngôn ngữ khác là -32768 –

+0

@JaromandaX ... phải là '- (2^53 + 1)'? Tôi không biết ... chỉ đơn thuần là tò mò. – rnevius

Trả lời

8

Giả sử bạn có số không dấu 8 bit.

Dưới đây là một lựa chọn các đại diện kỹ thuật số và nhị phân:

1: 00000001

2: 00.000.010

15: 00.001.111

255: 11111111

Nếu bạn có 255 và thêm 1, điều gì sẽ xảy ra? Không có nhiều bit, vì vậy nó kết thúc tốt đẹp xung quanh để

0: 00000000

Dưới đây là một cuộc biểu tình trong C# sử dụng uint (một unsigned 32-bit integer)

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

    } 
} 

chí này ra :

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

Đây là vấn đề bạn không gặp phải trong javascript.


Bạn gặp các sự cố khác nhau.

Ví dụ:

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

Bạn sẽ thấy:

n = 9007199254740991 và m = 9007199254740992 và p = 9007199254740992

Thay vì wrappin g xung quanh, đại diện số của bạn sẽ đổ chính xác.


Lưu ý rằng hành vi 'chính xác đổ' này không phải là duy nhất cho javascript, đó là những gì bạn mong đợi từ các loại dữ liệu dấu phẩy động. Một ví dụ khác 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;     
     } 
    } 
} 

Sản lượng này sẽ:

n = 16777210 
(n+1) - n = 1 
n = 16777220 
(n+1) - n = 1 
n = 16777220 
(n+1) - n = 0 
n = 16777220 
(n+1) - n = 0 
Các vấn đề liên quan