2010-01-13 41 views
8

Tôi có thuật toán/tính toán trong Java và kiểm tra đơn vị cho nó. Kiểm tra đơn vị mong đợi kết quả với một số độ chính xác/delta. Bây giờ tôi chuyển algo vào .NET và muốn sử dụng cùng một bài kiểm tra đơn vị. Tôi làm việc với kiểu dữ liệu kép.Thư viện cho điểm nổi chính xác trong .NET

Vấn đề là Java sử dụng strictfp (64 bit) cho một số thao tác trong lớp Toán. Khi .NET sử dụng FPU/CPU luôn (80 bit). .NET chính xác hơn và nhanh hơn. Java dễ dự đoán hơn.

Vì bản ngã của tôi là tuần hoàn và tái sử dụng kết quả từ vòng trước, lỗi/chênh lệch/độ chính xác hơn tích lũy quá lớn. Tôi không dựa vào tốc độ (để kiểm tra đơn vị). Và tôi rất vui khi sử dụng độ chính xác .NET trong sản xuất, nhưng tôi muốn xác thực việc triển khai.

Hãy xem xét điều này từ JDK


public final class Math { 
    public static double atan2(double y, double x) { 
    return StrictMath.atan2(y, x); // default impl. delegates to StrictMath 
    } 
} 

Tôi đang tìm thư viện hoặc kỹ thuật để sử dụng nghiêm ngặt FP trong .NET.

Nhận xét ưu tiên: Tôi hiểu định dạng IEEE 754 và thực tế là số dấu phẩy động không phải là số thập phân hoặc phân số chính xác. Không có thập phân, không có BigInt hoặc BigNumber. Xin đừng trả lời theo cách này, cảm ơn.

+3

Tôi không hiểu thử nghiệm đơn vị của bạn đang thử nghiệm gì nếu bạn sử dụng các triển khai toán toán dấu phẩy động khác nhau giữa Thử nghiệm và Sản xuất Đơn vị. Bạn không chạy các nguy cơ không bắt gặp một lỗi mà chỉ biểu hiện với việc thực hiện .NET? –

+0

Bản ngã/toán là một phần của bài kiểm tra tích hợp lớn hơn. Vì vậy, tôi cần thành phần này để hành xử giống hệt nhau. Chỉ cần cho thử nghiệm nó cần phải có cùng (nghiêm ngặt) làm tròn như Java, mà thực sự là ít chính xác hơn. –

+0

Nó thậm chí còn tệ hơn nữa. Thảo luận này cho thấy rằng CLR có thể quyết định biên dịch mã để sử dụng điểm nổi 80-bit x87 hoặc 64 bit SSE2: https://connect.microsoft.com/VisualStudio/feedback/details/276107/provide-access -to-the-floating-point-context –

Trả lời

2

Thật không may là không có cách nào để thực thi nghiêm ngặt FP trong C#, .Net CLR chỉ thiếu khả năng thực hiện các phép tính với độ chính xác thấp hơn mức tối đa có thể.

Tôi nghĩ rằng có hiệu suất đạt được điều này - nó không kiểm tra rằng bạn có thể muốn độ chính xác kém hơn. Cũng không cần - .Net không chạy trong một máy ảo và do đó không lo lắng về các bộ xử lý điểm nổi khác nhau.

Tuy nhiên không phải là strictfp tùy chọn? Bạn có thể thực thi mã Java của mình mà không có công cụ sửa đổi strictfp không? Sau đó, nó sẽ chọn cùng một cơ chế dấu chấm động như .Net

Vì vậy, thay vì buộc .Net để sử dụng strictfp và kiểm tra nó đi kèm với các giá trị giống như mã Java của bạn, bạn có thể buộc Java không sử dụng strictfp và kiểm tra sau đó nó xuất hiện giống như mã .Net.

+1

Đó là ý tưởng hay. Tôi có lẽ sẽ cần phải reimplement java Math lớp để không sử dụng strictfp và hy vọng rằng nó không được thực hiện như strinc trong mã nguồn gốc của thời gian chạy. Nhưng nó không giải quyết được vấn đề hoàn toàn (bây giờ tôi chỉ là nitpicking). Bởi vì tôi có một số kết quả mong đợi liên tục hardcoded trong mã, vì vậy nếu tôi chạy thử nghiệm đơn vị trên phần cứng khác nhau sau này, nó sẽ thất bại .... Vâng, không có câu trả lời tốt hơn anyway, bạn thắng cuộc đua :-) –

2

Tôi đã nghiên cứu rộng rãi vấn đề này vào đầu năm nay vì tôi muốn biết liệu có thể xây dựng mô phỏng nhiều người chơi trên số học dấu chấm động trong .NET hay không. Một số phát hiện của tôi có thể hữu ích cho bạn:

It is possible to emulate "strict" mode by inserting redundant casts everywhere, nhưng điều này dường như là một giải pháp dễ vỡ, C# đặc biệt và tẻ nhạt.

JIT 32 bit phát ra hướng dẫn x87, nhưng JIT 64 bit phát ra các chỉ lệnh SSE. Điều này đúng với cả việc triển khai Microsoft và Mono. Không giống như x87, SSE floating arithmetic is reproducible. Tôi tin rằng System.Math chỉ đơn giản gọi các hàm thời gian chạy C tương đương, mặc dù tôi đã không thể bước vào hội đồng để xác minh điều này (nếu ai đó biết cách thực hiện việc này, vui lòng kiểm tra!). Thời gian chạy C sử dụng các phiên bản SSE của các hàm siêu việt khi có thể, ngoại trừ trong một vài trường hợp, đặc biệt là sqrt (nhưng viết một trình bao bọc thông qua các công cụ cho điều đó là tầm thường). Bởi bản chất của SSE, chúng phải được tái sản xuất. It is programatically possible to determine whether the C runtime is using its SSE implementation rather than x87.

Đối với các chức năng siêu việt còn lại không có sẵn trong SSE (fmod, sinh, cosh, tanh), có thể là chúng không gây ra vấn đề tái lặp lại nếu không thực hiện thêm thao tác trên x87.

Vì vậy, trong ngắn hạn, gắn bó với CLR 64 bit nên giải quyết vấn đề cho số học; cho các hàm siêu việt, phần lớn được thực hiện trong SSE và tôi thậm chí không chắc chắn rằng điều đó là cần thiết nếu bạn không thực hiện bất kỳ số học x87 nào với kết quả.

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