2013-10-17 15 views
7

Nếu tôi đã biểu thức sau đây:Implicit chuyển đổi/thúc đẩy float hay double trong các biểu thức giữa C# và Java

byte A = 69; 
int B = 123; 
long C =; 
float D = 4.9f; 
double E = 11.11; 

double X = (B * 100) + 338.1 - (E/B)/C; 
double X1 = (B * 100) + (A * D) - (E/B)/C; 

// JAVA - lost precision 
System.out.println(X); // 12638.099971861307 
System.out.println(X1); // 12638.099581236307 

// C# - almost the same 
Console.WriteLine(X); // 12638.0999718613 
Console.WriteLine(X1) // 12638.0999784417 

tôi nhận thấy rằng Java mất độ chính xác từ X nơi 338,1 là ngầm đôi khi C# hầu như không . Tôi không hiểu tại sao vì 338.1 bằng bằng float và gấp đôi. Chỉ có một chữ số sau dấu chấm.

+1

338.1 KHÔNG giống hệt nhau trong float và double. Việc mở rộng nhị phân chính xác của 338.1 lặp đi lặp lại mãi mãi, vì vậy khi được biểu diễn dưới dạng gấp đôi, nó có nhiều chữ số khác 0 khi được biểu diễn dưới dạng float. –

+1

vui lòng đọc http://csharpindepth.com/Articles/General/FloatingPoint.aspx – Rohit

Trả lời

1

Trong Java, (B * 100) + (A * D) sẽ là một phao; và nó sẽ là phao gần nhất với 12638.1. Tuy nhiên, 12638 yêu cầu 14 chữ số để thể hiện dưới dạng nhị phân, bao gồm cả số 1 ban đầu; trong đó để lại 10 chữ số của phần tử và để diễn tả phần phân số. Vì vậy, bạn sẽ nhận được số lượng gần nhất từ ​​1024 đến 0,1 - tức là 102/1024. Điều này hóa ra là 0,099609375 - vì vậy phao có lỗi làm tròn là 0,000390625.

Điều đó có vẻ là sự khác biệt giữa X và X1 mà bạn đang nhận được trong chương trình Java của mình.

Tôi e rằng tôi không phải là chuyên gia về C#, vì vậy tôi không thể cho bạn biết tại sao C# lại khác.

0

Điều này liên quan đến việc giải thích trình biên dịch biểu thức của bạn. Vì bạn chưa chỉ định bất kỳ chuyển đổi loại trung gian nào, trình biên dịch thực hiện A * D làm chuyển đổi loại đầu tiên và sau đó nhân, thay vì ngược lại mà bạn mong đợi. Điều này có vẻ giống như một kết quả lạ, nhưng nó là một cách để trình biên dịch cung cấp cho bạn một kết quả chính xác hơn mà không cần phải chỉ định các chuyển đổi kiểu tẻ nhạt.

Java không xử lý điều này cho bạn và do đó, (B * 100) + (A * D) là phép nhân của intfloat - dẫn đến float. Điều này có thể được mô phỏng trong C# như sau:

double X2 = (float)((B * 100) + (A * D)) - (E/B)/C; 
Console.WriteLine("X2: {0}", X2); 

Đây là một trong những lợi thế (hoặc một số lợi ích có thể nói) của trình biên dịch cấp cao.

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