2013-07-12 28 views
5

Các abs chức năng sau đôi khi trả -0 (trừ zero)Thật kỳ lạ, tại sao hàm abs của tôi trả về -0?

inline float abs(float a){ 
    return(a>=0.0f? a :-a); 
} 

Để cụ thể hơn, báo cáo kết quả sản xuất sprintf(str, "%.2f", abs(-0.00f)); "-0,00", và đó là gây phiền nhiễu từ các chuỗi được hiển thị cho người dùng.

Câu hỏi:

1) Tại sao sản phẩm -0?

2) Cách khắc phục?

PS: Tôi đang sử dụng trình biên dịch c của xcode (mục tiêu).

+5

Chỉ tò mò .. bất kỳ lý do nào bạn không sử dụng 'fabs' và' fabsf'? –

+1

@JamesWebster Được rồi, fabs sẽ khắc phục được sự cố!Nhưng fabs được triển khai như thế nào và có gì sai với việc triển khai của tôi? – ragnarius

+0

@ragnarius nó sẽ xuất: '-0.00' –

Trả lời

2
  1. -0 là một tạo phẩm biểu diễn nhị phân, 0 với bộ bit dấu. Wikipedia có a comprehensive article on signed zero nếu bạn muốn biết thêm chi tiết.

  2. Sử dụng fabs() như những người đã nói ở trên. Nếu bạn thực sự thực sự muốn nội tuyến, hãy so sánh các so sánh của bạn:

    abs nổi bên trong (phao a) { return (a> 0.f)? a: ((a < 0.f)? -a: 0); }

12
  1. -0.0 == 0.0 và do đó -0.0 >= 0.0 là đúng.

  2. Sử dụng fabs (hoặc fabsf cho phao thay vì double) thay vì cố gắng phát minh lại nó.

+1

Thật thú vị khi 'printf' xác định khi nào xuất' -' ký tên. Chắc chắn nó không so sánh với số không vì -0.0 không nhỏ hơn 0.0. – Inspired

+2

Với tôi, không rõ ràng là -0.0 == 0.0. Biểu diễn nhị phân của -0.0 và 0.0 là khác nhau, và tôi đã đoán rằng hai phao bằng nhau nếu và chỉ khi biểu diễn nhị phân của chúng bằng nhau (nhưng sau đó tôi đã đoán sai, ít nhất là đối với một số trình biên dịch) – ragnarius

+3

@ragnarius: không thực sự là một vấn đề trình biên dịch, nhưng nó là một phần của tiêu chuẩn IEEE 754. Hầu hết các triển khai ít nhất là tuân thủ theo tiêu chuẩn IEEE 754, và những ứng dụng không thường hỗ trợ '-0.0'. –

2

Sử dụng signbit() để phân biệt. Làm việc với -0 và -INF và, tôi nghĩ, -NAN (nếu có một điều như vậy).

// C11 
inline float ragnarius_abs(float a) { 
    return signbit(a) ? -a : a; 
} 

Là tại sao a = -0.0f; a>=0.0f? a :-a; sản xuất -0?
-0.0f >= 0.0f là đúng: -0.0f0.0f đều số lượng bằng nhau, do đó a, được -0.0f được trả về.


ghi chú thêm về các loại dấu chấm động:

-0 bằng 0. Đây là điểm trừ duy nhất nổi nơi 2 nhị phân IEEE 754 đại diện chút khác nhau so sánh như bằng nhau. Một số định dạng điểm nổi khác có các biểu diễn bit khác nhau đại diện cho cùng một giá trị số.

NAN không bằng NAN. NAN có thể được biểu diễn bằng nhiều biểu diễn, nhưng ngay cả khi 2 NAN có cùng biểu diễn bit giống nhau, chúng sẽ không bằng số (==) so sánh như nhau.

+0

OK! Là ký hiệu được định nghĩa trong C (hoặc chỉ trong C++ 11?)? – ragnarius

+0

Bạn có nghĩ rằng fabs() được thực hiện theo cách này không? – ragnarius

+1

'signbit()' là C11. Phụ lục dự thảo C11 F.10.4.2 cho biết fabs (± 0) trả về +0. Vì vậy, có khả năng ragnarius_abs() đơn giản là tái tạo 'fabs()'. Oh well. – chux

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