2012-04-01 46 views
14

Như mọi người đều biết, bạn có độ chính xác giới hạn khi bạn sử dụng printf để xuất giá trị của float.
Tuy nhiên, có một mẹo để tăng độ chính xác trong đầu ra, như ví dụ này cho thấy:Độ chính xác của phao nổi với printf

#include <stdio.h> 

int main() 
{ 
    float f = 1318926965;  /* 10 random digits */ 
    printf("%10.f\n", f);  /* prints only 8 correct digits */ 
    printf("%10d\n", *(int*)&f); /* prints all digits correctly */ 
    return 0; 
} 

và câu hỏi của tôi là, tại sao không phải là người sử dụng thủ thuật này thường xuyên hơn?

+1

Do hành vi có khả năng không xác định là xấu. (Edit: Về mặt kỹ thuật nó có thể không phải là hành vi không xác định, vì tôi không chắc những gì tiêu chuẩn nói về nó. Endianess có thể cắn bạn với điều này mặc dù.) – Corbin

+8

+1 cho một trò đùa đầu tiên của tháng tư tốt! – Henrik

+0

Nó dường như đã cho tôi x.x – Corbin

Trả lời

11

Đánh lừa tháng 4?

"Số ngẫu nhiên" 1318926965 của bạn có cùng biểu diễn cơ bản cả ở dạng thập phân và dấu phẩy động.

Hãy thử một giá trị khác, như 10. Nó sẽ in như:

 10 
1092616192 

Vì vậy, để trả lời câu hỏi của bạn:

and my question is, why don't people use this trick more often? 

Bởi vì chỉ có một ngày trong năm là ngày Cá tháng tư ... Phần còn lại của những ngày lừa không hoạt động ...

4

Hãy thử điều đó lừa tương tự với một số khác, nói 2318926965.

#include <stdio.h> 

int main() 
{ 
    float f = 2318926965;  /* 10 random digits */ 
    printf("%10.f\n", f);  /* prints only 8 correct digits */ 
    printf("%10d\n", *(int*)&f); /* prints all digits correctly */ 
    return 0; 
} 
$ gcc -Wall -O3 t.c 
t.c: In function ‘main’: 
t.c:7:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 
$ ./a.out 
2318926848 
1326069764 

Tôi không thấy sự gia tăng độ chính xác ở tất cả với "lừa" của bạn mà phụ thuộc vào các đại diện chút của phao nổi trên nền tảng của bạn (theo như tôi hiểu).

This thread có một vài trong số các "phao phép thuật" này và cách tạo chúng.

+0

Nó phụ thuộc vào biểu diễn bit của phao cho mỗi IEEE 754, không phải "trên nền tảng của bạn". IMO điều duy nhất xấu về mã như thế này là không đúng kiểu-punning mà nên được thay thế bằng các công đoàn (sơ sài nhưng cố ý hỗ trợ bởi tất cả các trình biên dịch) hoặc 'memcpy' (100% hợp pháp C). –

+0

Nếu IEEE 754 là bắt buộc, việc sử dụng định nghĩa '__STDC_IEC_559__' là gì? – Mat

+0

Nó không phải là bắt buộc, nhưng xem xét việc phá vỡ tiêu chuẩn C cho phép các điểm triển khai thực hiện không tuân thủ IEEE, và không có cách nào khác bạn có thể nói những gì bạn có thể dựa vào liên quan đến số học dấu chấm động, tôi sẽ xem xét nó một sai lầm lớn đối với các chương trình muốn di chuyển sang các hệ thống không phải IEEE-toán học để sử dụng dấu phẩy động. (Tuy nhiên, bạn có thể sử dụng nó trên một chương trình không di động chỉ nhằm mục đích sử dụng trên một triển khai không phải là IEEE-toán đơn.) –

0

Giới hạn về độ chính xác là với biểu diễn dấu phẩy động, không phải với printf() đó là tiền đề sai.

Hơn nữa, một phao chính xác duy nhất chỉ được đảm bảo chính xác đến 6 chữ số chính xác, do đó, "mẹo" sẽ đánh lừa chính bạn; trong trường hợp chung nó sẽ không hoạt động.

Nếu bạn muốn có 10 chữ số dấu phẩy động thì bạn nên sử dụng độ chính xác gấp đôi, điều này tốt cho 15 chữ số.

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