2015-05-27 13 views
8

Nếu số của JavaScript và C# đôi được chỉ định giống nhau (IEEE 754), tại sao các số có nhiều chữ số có nghĩa được xử lý khác nhau?Tại sao các số có nhiều chữ số có ý nghĩa được xử lý khác nhau trong C# và JavaScript?

var x = (long)1234123412341234123.0; // 1234123412341234176 - C# 
var x =  1234123412341234123.0; // 1234123412341234200 - JavaScript 

Tôi không quan tâm đến thực tế là IEEE 754 không thể đại diện cho số 1234123412341234123. Tôi lo ngại với thực tế là hai ngôn ngữ này không hành động tương tự cho số mà không thể được đại diện một cách chính xác đầy đủ.

này có thể do IEEE 754 đang được chỉ định, một hoặc cả hai hiện thực đang bị lỗi hoặc rằng họ thực hiện các biến thể khác nhau của IEEE 754.

Vấn đề này không liên quan đến các vấn đề với sản lượng điểm định dạng trong C# nổi. Tôi đang xuất ra các số nguyên 64 bit. Hãy xem xét những điều sau đây:

long x = 1234123412341234123; Console.WriteLine(x); // Prints 1234123412341234123 double y = 1234123412341234123; x = Convert.ToInt64(y); Console.WriteLine(x); // Prints 1234123412341234176

Các bản in cùng một biến chuỗi khác nhau vì các giá trị khác nhau.

+0

Tại sao bạn truyền đến lâu? –

+0

Bạn đang so sánh một đôi với một phao tôi nghĩ. nếu bạn muốn để có thể tính toán với số lượng lớn lớn, tôi đề nghị bạn sử dụng http://mikemcl.github.io/decimal.js/ và cung cấp số chuỗi loại để có được số chữ số bạn muốn. Điều này không trả lời câu hỏi của bạn nhưng có thể giúp ích một chút nếu bạn đang gặp phải vấn đề. Số lớn thường được lưu dưới dạng giá trị công thức và lỗi làm tròn có thể xảy ra do đó. Đó là lý do tại sao các điểm nổi không chính xác. Bạn có thể đã vấp ngã vào một số lớn làm tròn không chính xác trong javascript. Đối với những lý do có thể nhìn vào https://code.google.com/p/v8/ – Tschallacka

+0

Có một vấn đề thú vị ở đây ... Các NET thường chỉ cho thấy 15 chữ số chính xác, thay vì toàn bộ 17. – xanatos

Trả lời

3

Có nhiều vấn đề ở đây ...

Bạn đang sử dụng long thay vì double. Bạn sẽ cần phải viết:

double x = 1234123412341234123.0; 

hoặc

var x = 1234123412341234123.0; 

Vấn đề khác là NET vòng double s đến 15 chữ số trước khi chuyển đổi nó để string (vì vậy trước khi ví dụ in nó với Console.ToString()).

Ví dụ:

string str = x.ToString("f"); // 1234123412341230000.00 

Xem ví dụ https://stackoverflow.com/a/1658420/613130

Bên số vẫn là với 17 chữ số, chỉ có nó được hiển thị với 15.

Bạn có thể nhìn thấy nó nếu bạn làm một :

string str2 = x.ToString("r"); // 1.2341234123412342E+18 
2

Số không được xử lý khác nhau, chúng là chỉ hiển thị khác nhau.

.NET hiển thị số có 15 chữ số có nghĩa, trong khi JavaScript hiển thị số đó với 17 chữ số có nghĩa. Biểu diễn của một đôi có thể chứa 15-17 chữ số có nghĩa, tùy thuộc vào số lượng nó chứa. .NET chỉ hiển thị số chữ số mà số được đảm bảo luôn hỗ trợ, trong khi JavaScript hiển thị tất cả các chữ số nhưng giới hạn chính xác có thể hiển thị. Bắt đầu bằng cách sử dụng ký pháp khoa học khi số mũ là 15, trong khi JavaScript bắt đầu sử dụng nó khi số mũ là 21. Điều đó có nghĩa là JavaScript sẽ hiển thị số có 18 đến 20 chữ số được đệm bằng số 0 ở cuối.

Chuyển đổi double thành long trong ví dụ của bạn sẽ phá vỡ cách Hiển thị .NET tăng gấp đôi. Số lượng sẽ được chuyển đổi mà không làm tròn làm ẩn giới hạn chính xác, vì vậy trong trường hợp này, bạn sẽ thấy giá trị thực tế ở mức gấp đôi.Lý do không có chỉ số 0 vượt quá chữ số 17 là giá trị được lưu trữ dưới dạng nhị phân, chứ không phải dạng thập phân.

1

Disclaimer: Đây là dựa trên các tiêu chuẩn wikipedia page

Theo trang wikipedia cho tiêu chuẩn, nó xác định rằng một decimal64 nên có 16 chữ số chính xác.

Past rằng đó là quyết định thực hiện chính như những gì nên được thực hiện với các chữ số bổ sung.

Vì vậy, bạn có thể nói rằng tiêu chuẩn là underspecified nhưng sau đó những con số này không được thiết kế để phù hợp trong các thông số kỹ thuật tiêu chuẩn anyway. Cả hai ngôn ngữ đều có cách xử lý các số lớn hơn để các tùy chọn này có thể phù hợp hơn với bạn.

+0

16 chữ số chính xác được uỷ quyền dường như ngụ ý cả .NET và Chrome bị phá vỡ kể từ khi số 9111234123412341 được thay đổi để 9111234123412340 trong cả hai hiện thực. –

+0

@HansMalherbe - Nhưng bạn đang đánh giá này dựa trên chuỗi đại diện của họ chứ không phải là con số thực tế (Trong C# ít nhất họ nhận được hiển thị tới [15 sf] (http://stackoverflow.com/a/1658420/1324033)) – Sayse

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