2015-05-06 52 views
7

Ví dụ:Trình biên dịch C và C++ thực hiện quyết định bình đẳng cho các số phao như thế nào?

float a = 1.0; 
float b = 1.2; 

puts(a == b? "equal": "not equal"); 

Trình biên dịch có xử lý một chút hoặc bằng một số phương pháp khác không?

(Tôi biết nó không phải là một lựa chọn tốt để quyết định sự bình đẳng của số dấu chấm động bởi "==", tôi chỉ muốn biết làm thế nào một giao dịch biên dịch với tình trạng này.)

+1

Sự khác biệt giữa bitwise và theo giá trị là gì? Chắc chắn chúng giống nhau đối với phao nổi –

+0

@EdHeal đúng, vấn đề được chỉnh sửa – Wizmann

+5

Tất cả các số dấu phẩy động được lưu trữ trong ** Định dạng điểm nổi IEEE-754 **. Chúng là ** 32-bit ** (điểm nổi chính xác đơn) hoặc ** 64-bit ** (điểm nổi chính xác gấp đôi). Có nghĩa là có một số nguyên tương đương với mỗi số dấu phẩy động dựa trên các bit trong bộ nhớ. Trình biên dịch xử lý nó giống như cách nó thực hiện một số nguyên có kích thước tương đương. Xem: [** Hướng dẫn nổi điểm - Điều mà mọi lập trình viên nên biết ... **] (http://floating-point-gui.de/) –

Trả lời

5

Câu trả lời chung, đầy đủ là các số dấu phẩy động được so sánh theo đặc điểm kỹ thuật IEEE 754.

Để trả lời câu hỏi của bạn đặc biệt, phần lớn thời gian hai số dấu chấm động được so sánh Bitwise, với một vài trường hợp ngoại lệ:

  • không tích cực và tiêu cực được coi là bình đẳng
  • NaN được coi là bất bình đẳng để tất cả mọi thứ, thậm chí đến NaN tự
  • subnormals thể so sánh bằng số không và subnormals khác trong chế độ hoạt động nhất định (ví dụ: "subnormals tuôn ra để zero")
  • khác với những cựu ceptions, so sánh bitwise thông thường được sử dụng
+3

... ngoại trừ, tất nhiên, khi hệ thống không sử dụng điểm nổi IEEE (ví dụ: một số máy tính lớn của IBM vẫn không, một số ít GPU không, ít nhất là thường). –

+1

C++ không yêu cầu IEEE754 (mặc dù [có một biến tĩnh, bạn có thể kiểm tra xem ieee754 có đang được sử dụng hay không] (http://stackoverflow.com/questions/5777484/how-to-check-if-c-compiler -us-ieee-754-floating-point-standard)). –

1

Tôi giả sử bạn có nghĩa là sau khi chương trình được biên dịch, nó so sánh hai phao như thế nào. Cách nổi được lưu trữ là rất độc đáo. Nó được lưu trữ bằng dấu, số mũ và phân số như đã thấy here. Vì vậy, trừ khi nó là hoàn toàn bình đẳng, chương trình sẽ thấy ngay cả 1 và 1,000000000001 là khác nhau. Để kiểm tra xem họ là gần bằng nhau, bạn có thể sử dụng như sau:

bool AlmostEqualRelativeOrAbsolute(float A, float B, 
      float maxRelativeError, float maxAbsoluteError) 
{ 
    if (fabs(A - B) < maxAbsoluteError) 
     return true; 
    float relativeError; 
    if (fabs(B) > fabs(A)) 
     relativeError = fabs((A - B)/B); 
    else 
     relativeError = fabs((A - B)/A); 
    if (relativeError <= maxRelativeError) 
     return true; 
    return false; 
} 

Mã này được lấy từ here, bạn có thể muốn đọc thêm tại trang web.

3

gcc và clang sử dụng hướng dẫn UCOMISS x86/x64.

Nguồn: tried it với -O3 và kiểm tra đầu ra lắp ráp.

+5

Nói chung, trình biên dịch tạo ra một hướng dẫn cụ thể về kiến ​​trúc để so sánh các số dấu phẩy động nếu kiến ​​trúc có hỗ trợ phần cứng cho chúng - chẳng hạn như x86, x86-64 và ARM - nếu không nó sẽ phát ra một chuỗi các lệnh thực hiện hành vi yêu cầu theo tiêu chuẩn dấu phẩy động đang được sử dụng, hầu như luôn là IEEE-754. –

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