2010-09-20 43 views
10

Đây là những gì xảy ra trên máy tính của tôi:Tại sao (gấp đôi) 0.6f> (gấp đôi) (6/10f)?

(double)(float)0.6 
= 0.60000002384185791 

(double)0.6f 
= 0.60000002384185791 

(double)(6/10f) 
= 0.6 

(double)(float)(6/10f) 
= 0.6 

6/10f cũng là một phao, làm thế nào mà nó có thể được chính xác 0.6?
Trong tâm trí tôi (gấp đôi) (6/10f) cũng phải là 0,60000002384185791. Ai đó có thể giúp giải thích điều này? cảm ơn!

+0

Bằng cách này trong Java, kết quả là 0,6000000238418579 cho tất cả những điều trên. –

+0

Tôi đang sử dụng cửa sổ ngay lập tức. Tôi đã thử nghiệm trong chương trình, họ không bằng nhau.Vì vậy, nó không phải là một vấn đề của foramtting. – zhy2002

+0

http://stackoverflow.com/questions/1778368/python-float-str-float-weirdness – Sharun

Trả lời

5

Thứ nhất, nó quan trọng cần ghi nhớ rằng 0.6 không thể được đại diện một cách chính xác như một float tuy nhiên nó thể được đại diện một cách chính xác như một double (không chính xác của dấu chấm động số học cũng là tài liệu, nếu nó không rõ ràng lý do tại sao 0.6 không thể được biểu diễn chính xác dưới dạng phao, hãy thử this link)

Lý do tại sao bạn nhìn thấy hành vi trên xuống trình biên dịch - nếu bạn nhìn vào bộ biên dịch trong bộ phản xạ thì những gì đang diễn ra ở đây hơi rõ ràng hơn:

(CẬP NHẬT Tôi đã thay đổi mã để nó không sử dụng Console.WriteLine, như tôi nhận ra rằng trình biên dịch được lựa chọn một tình trạng quá tải cho bạn, mà lẫn lộn tình hình)

// As written in source 
var j = (double)(float)0.6; 
var k = (double)0.6f; 
var l = (double)(6/10f); 
var m = (double)(float)(6/10f); 

// Code as seen by Reflector 
double j = 0.60000002384185791; 
double k = 0.60000002384185791; 
double l = 0.6; 
double m = 0.6; 

Tại sao trình biên dịch chọn biên dịch theo cách đặc biệt này là ngoài tôi (FYI, đây là tất cả với optimisations tắt)

Một số trường hợp khác thú vị:

// Code 
var a = 0.6; 
var b = (double)0.6; 
var c = 0.6f; 
var d = (float)0.6; 

var e = 6/10; 
var f = 6/(10f); 
var g = (float)(6/10); 
var h = 6/10f; 
var i = (double)6/10; 
// Prints out 0.60000002384185791 

double n = (float)0.6; 
double o = f; 

// As seen by Reflector 
double a = 0.6; 
double b = 0.6; 
float c = 0.6f; 
float d = 0.6f; 

int e = 0; 
float f = 0.6f; 
float g = 0f; 
float h = 0.6f; 
double i = 0.6; 

double n = 0.60000002384185791; 
double o = f; 

Trình biên dịch chỉ dường như để làm ab ove lừa trong một vài trường hợp đặc biệt, tại sao nó chỉ này khi đúc đến một đôi là hoàn toàn vượt ra ngoài tôi!

Phần còn lại của thời gian dường như làm một số thủ thuật để làm cho số học dấu phẩy động dường như để hoạt động ở nơi thực tế bình thường thì không.

+0

Điều thú vị là, nếu bạn sử dụng 'float', tất cả chúng sẽ in 0,6 (như được thấy trên [ideone] (http://ideone.com/2lvBI), cũng được thử nghiệm với Visual C#) – NullUserException

+0

Cảm ơn mọi người, tôi nghĩ nó thực sự một vấn đề cụ thể của trình biên dịch. – zhy2002

+0

Ngoài ra tôi thấy rằng: float float3 = 0.6f; int int1 = 6; float1 = 10; Assert.IsTrue (int1/float1> = float3); // thất bại, Trong mã float3 của tôi là một đối số! – zhy2002

2

Dường như làm tròn kết quả. Bạn có hiển thị kết quả với các chữ số chính xác cần thiết không? Bạn có thể sử dụng this c# class từ Jon Skeet để có được biểu diễn số chính xác của kết quả được in ra.

Lưu ý rằng ToString() sẽ không luôn luôn in tất cả các chữ số, cũng như trình gỡ lỗi Visual Studio.

1

Nếu tôi là cá cược, tôi muốn nói sự khác biệt là ở nơi xảy ra sự ép buộc. Trong hai ví dụ sau (những cái có 6/10f), có hai chữ cái là cả hai số nguyên (số nguyên 6 và số float 10.00000000 ...). Việc phân chia dường như xảy ra sau khi bị ép buộc, ít nhất là trong trình biên dịch bạn đang sử dụng. Trong hai ví dụ đầu tiên, bạn có một chữ phẩy phân đoạn (0.6) mà không thể được biểu diễn đầy đủ như một giá trị nhị phân trong mantissa của một phao. Co giật rằng giá trị cho một đôi không thể sửa chữa thiệt hại đã được thực hiện.

Trong môi trường đang tạo ra kết quả hoàn toàn nhất quán, sự phân chia xảy ra trước khi cưỡng chế tăng gấp đôi (6 sẽ bị ép cho phao để phân chia khớp với 10, phân chia được thực hiện trong không gian nổi, sau đó kết quả là bị ép buộc thành gấp đôi).

+0

Bạn luôn có thể sử dụng ildasm để xem những gì đã xảy ra bằng cách sử dụng ildasm và nhìn vào hội đồng trung gian được tạo ra. –

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