2012-05-29 35 views
10

Giả sử rằng t, a, b đều tăng gấp đôi (IEEE Std 754) biến, và cả hai giá trị của a, b KHÔNG NaN (nhưng có thể Inf). Sau t = a - b, tôi có nhất thiết phải có a == b + t không?IEEE Std 754 Floating-Point: let t: = a - b, tiêu chuẩn có đảm bảo rằng a == b + t không?

+0

Tôi tin rằng kết quả của một dòng dưới sẽ không xác định, và do đó sẽ là kết quả của một tràn trong biểu thức thứ hai, vì vậy không. Nếu ai đó có thể xác nhận điều đó, nó sẽ rất tuyệt. – chris

+0

Ah, tôi đoán loại xác nhận rằng tràn là không xác định cho dấu phẩy động quá: 'Như với bất kỳ số học nào khác trên, nếu kết quả không nằm trong khoảng trống được cung cấp, hành vi không được xác định.' – chris

+3

Trong triển khai C phù hợp với IEEE 754, không có UB cho bất kỳ số học dấu phẩy động nào. Tất cả các kết quả được xác định nghiêm ngặt. –

Trả lời

25

Tuyệt đối không. Một trường hợp hiển nhiên là a=DBL_MAX, b=-DBL_MAX. Sau đó, t=INFINITY, vì vậy b+t cũng là INFINITY.

Điều đáng ngạc nhiên hơn là có những trường hợp điều này xảy ra mà không bị tràn. Về cơ bản, tất cả chúng đều có dạng a-b không chính xác. Ví dụ, nếu aDBL_EPSILON/4b-1, a-b là 1 (giả sử chế độ làm tròn mặc định), và sau đó là a-b+b 0.

Lý do tôi đề cập đến ví dụ thứ hai này là rằng đây là kinh điển cách để buộc làm tròn đến độ chính xác cụ thể trong số học IEEE. Ví dụ, nếu bạn có một số trong phạm vi [0,1) và muốn bắt buộc làm tròn nó đến 4 bit chính xác, bạn sẽ cộng và trừ 0x1p49.

+1

Ví dụ thứ 2 là rất tốt vì nó không chịu Inf cũng không NaN. Cảm ơn rất nhiều. – updogliu

+1

Bạn có thể muốn làm rõ 'liên tục 0x1p49', lần cuối cùng tôi nhìn hex chữ số chạy từ 0 đến F;) – MSalters

+8

@MSalters: "0x1p49" là hệ thập lục phân dấu chấm động, theo quy định trong tiêu chuẩn C. Định dạng là "0x" "p" , nơi là một chữ số thập lục phân, tùy chọn bao gồm một khoảng thời gian, và là một chữ số thập phân, tùy chọn bao gồm một dấu hiệu. Căn cứ cho số mũ là hai, vì vậy 0x1p49 là 2 ** 49. 0x1p-4 sẽ là 1/16 và 0x1.23p8 sẽ là (1 + 2/16 + 3/256) * 2 ** 8 = 291. Dấu chấm động thập lục phân cung cấp định dạng dễ dàng cho con người và trình biên dịch để chuyển đổi đến và từ mã hóa dấu phẩy động nhị phân mà không làm tròn các vấn đề. –

1

Trong quá trình thực hiện thao tác đầu tiên, các bit có thể đã bị mất khỏi đầu thấp của kết quả. Vì vậy, một câu hỏi là, liệu hoạt động thứ hai sẽ tái tạo chính xác những tổn thất đó? Tôi chưa hoàn toàn nghĩ ra điều đó.

Nhưng, tất nhiên, hoạt động đầu tiên có thể đã tràn đến +/- vô cùng, hiển thị thứ hai so sánh không bằng nhau.

(Và dĩ nhiên, trong trường hợp tổng quát sử dụng == cho các giá trị dấu chấm động là hầu như luôn luôn là một lỗi.)

+1

Chỉ bằng một đối số đếm, thao tác thứ hai không thể mang lại những gì đã mất. Nếu có thể, bạn sẽ lưu trữ nhiều bit thông tin hơn trong 't' hơn số bit trong' t' ... –

+0

@R - Có. Trực giác người ta biết rằng nó sẽ không hoạt động, bởi vì những gì bạn nói, nhưng việc tìm kiếm các ví dụ là tốt hơn "bằng chứng" hơn hấp dẫn cho một quy tắc bí truyền, không có vấn đề như thế nào hợp lệ. –

-3

Bạn đang không được bảo đảm bất cứ điều gì khi sử dụng phao nổi. Nếu số mũ khác nhau cho cả hai con số, kết quả của phép toán số học có thể không được biểu diễn hoàn toàn trong một phao.

xem xét mã này:

float a = 0.003f; 
float b = 10000000.0f; 
float t = a - b; 
float x = b + t; 

Chạy trên Visual Studio 2010, bạn sẽ có được t==-10000000.0f, và do đó x==0.

Bạn không bao giờ nên sử dụng bình đẳng khi so sánh nổi. Thay vào đó, hãy so sánh giá trị tuyệt đối của sự khác biệt giữa cả hai giá trị và giá trị epsilon đủ nhỏ cho các nhu cầu chính xác của bạn.

Nó càng trở nên kỳ lạ hơn khi các điểm triển khai điểm nổi khác nhau có thể trả về các kết quả khác nhau cho cùng một thao tác.

+5

Tôi chưa bao giờ thích lời khuyên "so sánh giá trị tuyệt đối của sự khác biệt". Có thể bị giới hạn về lỗi ([Mỗi nhà khoa học máy tính nên biết gì về số học dấu chấm động] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) là một điều tốt bắt đầu) và người ta nên suy nghĩ về những gì người ta đang cố gắng thực hiện với so sánh trước khi chuyển đổi một cách mù quáng sang một số ràng buộc tùy ý. –

+8

Có rất nhiều thứ được đảm bảo khi sử dụng các phao nổi IEEE-754. Điều này xảy ra không phải là một trong số họ. –

+0

Có rất nhiều sự đảm bảo khi sử dụng IEEE nổi, và có những lúc khi so sánh bình đẳng không chỉ hợp lý, mà còn cần thiết. Toán học dấu chấm động chắc chắn phức tạp, nhưng nó không phải là ngẫu nhiên hay độc hại. Đây là một ví dụ từ blog của tôi khi thử nghiệm cho điểm bình đẳng nổi là rất quan trọng: https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/ –

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