2012-12-17 26 views
19

Addition toán học giữ tài sản kết hợp:Các hoạt động điểm nổi trong liên kết C?

(a + b) + c = a + (b + c) 

Trong trường hợp tổng quát, khách sạn này không giữ cho số dấu chấm động vì họ đại diện cho các giá trị trong một độ chính xác hữu hạn.

Trình biên dịch có được phép thực hiện thay thế ở trên khi tạo mã máy từ chương trình C như một phần của tối ưu hóa không? Nói chính xác ở đâu trong tiêu chuẩn C?

+1

Để nhân ít nhất, hãy xem tại đây: http://stackoverflow.com/questions/6430448/why-doesnt-gcc-optimize-aaaaaa-to-aaaaaa –

Trả lời

12

Trình biên dịch không được phép thực hiện "tối ưu hóa", điều này sẽ dẫn đến một giá trị khác được tính toán, so với giá trị được tính theo ngữ nghĩa máy trừu tượng.

5.1.2.3 thực hiện Chương trình

[# 1] Các mô tả ngữ nghĩa trong tiêu chuẩn quốc tế này mô tả hành vi của một máy trừu tượng trong mà vấn đề tối ưu hóa là không thích hợp.

[# 3] Trong máy trừu tượng, tất cả các biểu thức được đánh giá như được chỉ định bởi ngữ nghĩa.

[# 13] VÍ DỤ 5 Sắp xếp lại các biểu thức dấu phẩy động thường bị hạn chế do giới hạn về độ chính xác là cũng như phạm vi. Việc triển khai thường không thể áp dụng các quy tắc kết hợp toán học để bổ sung hoặc phép nhân, cũng không phải quy tắc phân phối, vì lỗi vi phạm , ngay cả khi không có tràn và tràn.

Trong ví dụ của bạn:

(a + b) + c 

hoặc thậm chí không có dấu ngoặc:

a + b + c 

chúng tôi có

+ 
/\ 
    + c 
/\ 
a b 

và trình biên dịch là cần thiết để tạo ra mã như thể a được tổng hợp với b và kết quả được tổng hợp với c.

+0

Lý thuyết chính xác. Ứng dụng mang về nhà là: tìm ra thứ tự các hoạt động của bạn sẽ xảy ra (ví dụ: nếu bạn muốn tổng hợp từ nhỏ đến nhỏ, lớn đến lớn), hãy đặt trong dấu ngoặc đơn để thỏa mãn hoang tưởng, và bạn có thể ngừng lo lắng về trình biên dịch. sắp xếp lại. –

+0

Tuy nhiên, lưu ý rằng khi quyền ưu tiên của toán tử được xác định rõ ràng, thứ tự đánh giá biểu thức phụ không được chỉ định. Nói cách khác, chương trình có thể đánh giá cây nhị phân này bắt đầu từ phải sang trái, hoặc từ trái sang phải, và thậm chí nó không phải giữ trật tự theo cách nhất quán, cũng như không cần phải ghi lại nó. Vì vậy, nếu a, b hoặc c chứa các tác dụng phụ ảnh hưởng đến kết quả, thì mã sẽ có vấn đề. Ví dụ: c là hàm sửa đổi a: thì chúng ta không thể biết kết quả. – Lundin

5

Nhân dấu chấm động trong C không phải là kết hợp.

In C, Floating point multiplication is not associative. 

Một số bằng chứng là với mã C này:

Pick ba giá trị float ngẫu nhiên.
Kiểm tra nếu a*(b*c) là bao giờ không bằng (a*b)*c

#include<stdio.h> 
#include<time.h> 
#include<stdlib.h> 
using namespace std; 
int main() { 
    int counter = 0; 
    srand(time(NULL)); 
    while(counter++ < 10){ 
     float a = rand()/100000; 
     float b = rand()/100000; 
     float c = rand()/100000; 

     if (a*(b*c) != (a*b)*c){ 
      printf("Not equal\n"); 
     } 
    } 
    printf("DONE"); 
    return 0; 
} 

Chương trình in:

Not equal 
Not equal 
Not equal 
Not equal 
DONE 
RUN FINISHED; exit value 0; real time: 10ms; user: 0ms; system: 0ms 

Kết luận:

Đối với thử nghiệm của tôi, ba giá trị nhân dấu chấm động lựa chọn ngẫu nhiên là kết hợp khoảng 70% thời gian.

+0

OP hỏi xem trình biên dịch * giả định * các hoạt động nổi có liên quan, khi nó thực hiện tối ưu hóa. Anh ta nhận thức rõ ràng rằng họ thực sự không. –

+0

Có nhưng nó luôn luôn tốt đẹp để xem một ví dụ mà xác nhận lý thuyết. –

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