2016-06-24 16 views
5

Như được giải thích ở nhiều nơi (chẳng hạn như Why can't decimal numbers be represented exactly in binary?), không phải tất cả các phân số thập phân có thể được biểu diễn dưới dạng giá trị dấu phẩy động (chẳng hạn như được lưu trữ trong một float trong Java).Làm thế nào có thể Java round-trip String -> float -> String ngay cả đối với (một số) giá trị không đại diện như một phao?

Ví dụ điển hình được đưa ra là "0,2". Theo điều này tiện lợi IEEE 754 Converter, số float gần nhất với 0,2 là khoảng 0,20000000298023224, do đó việc phân tích cú pháp "0,2" là float sẽ mang lại kết quả này.

Tuy nhiên, tôi lưu ý rằng Java dường như có thể làm được những điều không thể:

String number="0.2"; 
float f = Float.parseFloat(number); 
System.out.println("Result of roundtrip String -> float -> String: "+f); 

in:

quả của String khứ hồi -> float -> String: 0,2

Test on IDeone.com

Làm thế nào để Java biết rằng tôi muốn đầu ra (tròn) "0.2", thay vì đầu ra chính xác "0.20000000298023224" như đã giải thích ở trên?

Các Javadocs of Float.toString() cố gắng để giải thích điều này:

Có bao nhiêu chữ số phải được in cho các phần phân đoạn của m hay? Phải có ít nhất một chữ số đại diện cho phần phân đoạn và vượt quá số lượng đó, nhưng chỉ cần nhiều, nhiều chữ số càng cần để phân biệt duy nhất giá trị đối số từ các giá trị liền kề loại float.

Thật không may, điều này làm tôi bối rối hơn nữa. Tại sao "in bao nhiêu chữ số khi cần để phân biệt duy nhất giá trị đối số" cho phép Java in "0,2"?

Lý tưởng nhất, câu trả lời cũng sẽ giải thích lý do tại sao thuật toán in này đã được chọn. Nó là để làm cho một số chuyến đi khứ hồi hoạt động, như trong ví dụ này? Có động cơ nào khác không?

+1

Jon Skeet ở đâu khi bạn cần anh ấy? Anh ấy có BREXIT không? – GhostCat

+0

Bạn biết rằng thậm chí nhập 0,21 hoặc 0,2000001 hoặc bất cứ điều gì tương tự cũng trả về 0,2? Xem http://stackoverflow.com/questions/17464675/convert-string-to-decimal-number-with-2-decimal-places-in-java – mylenereiners

+0

Có 7 số 0, 10^7 = 2^23 có thể là 3 byte mantissa của một phao 4 byte đạt được. Vì vậy, ở đây nó vẫn có thể được thường xuyên. Thường thì C và C++ gian lận một chút để có kết quả đẹp hơn (ấn tượng của tôi). –

Trả lời

1

Tôi đoán 0,2 thuộc về "Value Set Conversion".

+0

Hm, tôi nghĩ đó là một khu vực khác (mặc dù có liên quan). Chuyển đổi tập hợp giá trị dường như áp dụng cho kết quả trung gian trong tính toán FP, không áp dụng cho chuyển đổi. – sleske

+0

Nhìn vào §5.2 của cùng một trang. – mauretto

2

Làm tròn đầu ra không phải do một số thuật toán in. Đó là vì kích thước của float. Nếu bạn làm:

String fs = "0.2"; 
double f = Float.parseFloat(fs); 
System.out.println(f); 

Bạn nhận:

0,20000000298023224

Test on Ideone.com

Điều này cho thấy rõ ràng rằng String "0.2" được phân tách như 0,20000000298023224, nhưng dữ liệu phao -type không thể giữ nó, và làm tròn nó lên đến 0,2. double loại dữ liệu có khả năng giữ dữ liệu này và do đó, khi bạn phân tích cú pháp đó là phao, nhưng lưu trữ nó trong một đôi, bạn sẽ nhận được kết quả mong đợi.

+0

Khi tôi phân tích cú pháp nó thành gấp đôi, nó vẫn dẫn đến 0,2 – 4castle

+0

Không. Trên IDE của tôi Đây là điều này. Chờ đã, tôi sẽ thử trực tuyến để cho bạn thấy. – Hackerdarshi

+0

@ 4castle Xem điều này: http://ideone.com/sjWAZS – Hackerdarshi

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