2012-01-18 19 views
16

lý do tại sao Double.parseDouble làm 9999999999999999 đến 10000000000000000? Ví dụ:tại sao Double.parseDouble lại làm 9999999999999999 thành 10000000000000000?

Double d =Double.parseDouble("9999999999999999"); 
String b= new DecimalFormat("#.##").format(d); 
System.out.println(b); 

IS In

10000000000000000 

thay vào đó nó có để hiển thị 9999999999999999 hoặc 9999999999999999.00

Bất cứ phương pháp giúp đỡ được đánh giá rất cao.

+11

dấu chấm động số học --- bí ẩn lớn nhất của khoa học máy tính từ năm 1985 – subsub

Trả lời

12

double thấy chỉ có 15/16 con số chính xác và khi bạn cho nó một số nó không thể đại diện (đó là hầu hết thời gian, thậm chí 0.1 là không chính xác) nó có số đại diện gần nhất.

Nếu bạn muốn đại diện cho 9999999999999999 chính xác, bạn cần sử dụng BigDecimal.

BigDecimal bd = new BigDecimal("9999999999999999"); 
System.out.println(new DecimalFormat("#.##").format(bd)); 

in

9999999999999999 

Rất ít các vấn đề thế giới thực cần độ chính xác này bởi vì bạn không thể đo lường một cách chính xác bất cứ điều gì này anyway. tức là lỗi 1 phần trên mỗi nghìn tỷ.


Bạn có thể tìm ra số nguyên biểu diễn lớn nhất với

// search all the powers of 2 until (x + 1) - x != 1 
for (long l = 1; l > 0; l <<= 1) { 
    double d0 = l; 
    double d1 = l + 1; 
    if (d1 - d0 != 1) { 
     System.out.println("Cannot represent " + (l + 1) + " was " + d1); 
     break; 
    } 
} 

in

Cannot represent 9007199254740993 was 9.007199254740992E15 

Các số nguyên biểu diễn lớn nhất là 9007199254740992 vì nó cần một ít bit (như thậm chí nó)

+1

Sẽ hữu ích hơn nếu sử dụng số học nhị phân khi suy nghĩ về việc tăng gấp đôi IEEE bình thường hơn là sử dụng một số loại xấp xỉ thập phân. –

+0

9007199254740992 = 20000000000000 (hex) = 100000000000000000000000000000000000000000000000000000 (bin) –

+0

@DonalFellows Đúng, đó là lý do tại sao tôi chỉ xem xét quyền hạn của 2. –

15

Số 9999999999999999 nằm ngay trên giới hạn chính xác của dấu phẩy động kép chính xác kép. Nói cách khác, mantissa 53 bit không thể giữ 9999999999999999.

Vì vậy, kết quả là nó được làm tròn thành giá trị chính xác kép gần nhất - là 10000000000000000.

9999999999999999 = 0x2386f26fc0ffff // 54 significant bits needed 
10000000000000000 = 0x2386f26fc10000 // 38 significant bits needed 
+0

+1: Chính xác điều này. Phải mất _54_ bit để đại diện cho một 9999999999999999 unsigned và giá trị lớn nhất mà sẽ phù hợp chính xác trong một đôi tiêu chuẩn là 9007199254740991. –

+0

@DonalFellows Nó sẽ không phải là một số chẵn?Nếu 9007199254740991 có thể được đại diện 9007199254740992 phải được đại diện là tốt. –

+0

@Peter: 0x1fffffffffffff là một số lẻ yêu cầu tối thiểu 53 bit để biểu diễn. Số lớn hơn yêu cầu 54 bit (hoặc số mũ). Đoán giá trị đó bằng số thập phân là gì? :-) –

5

9999999999999999 đòi hỏi 54 bit của mantissa để được đại diện một cách chính xác, và double chỉ có 52. Do đó, số được làm tròn đến số gần nhất thể được biểu diễn bằng một mantissa 52-bit. Con số này xảy ra là 10000000000000000.

Lý do 10000000000000000 yêu cầu ít bit hơn là biểu diễn nhị phân của nó kết thúc bằng rất nhiều số không và các số 0 này có thể được biểu diễn bằng cách tăng số mũ (nhị phân).

Đối với giải thích chi tiết của một vấn đề tương tự, Why is (long)9223372036854665200d giving me 9223372036854665216?

Các vấn đề liên quan