2012-04-01 32 views
14

printfを使用してfloatの値を出力すると、精度が制限されます。浮動小数点型の精度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; 
} 

を、人々はより頻繁にこのトリックを使用していない、なぜ私の質問は、次のとおりです。この例が示すように
しかし、出力の精度を向上させるコツは、ありますか?

+1

潜在的に未定義の動作が悪いため。 (編集:技術的には、規格が何を言っているのか分からないので、未定義の振る舞いではないかもしれませんが、エンディアンはあなたにこれをかけることができます) – Corbin

+8

良い4月1日のジョーク+1! – Henrik

+0

それは明らかに私をxxにした。 – Corbin

答えて

11

4月愚か者?

"乱数" 1318926965は、10進数と浮動小数点形式の両方で同じ基本的な表現を持ちます。

のような別の値を試してください。だからあなたの質問に答えるために

 10 
1092616192 

:それはように印刷されます

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

年の一日だけはエイプリルフールなので...日の残りの部分は、トリックは動作しません。 ...

4

、別の番号と同じトリックを試してみてくださいと言う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 

私は全くビット表現に依存してあなたの「トリック」と精度の向上が表示されません(あなたが理解している限り)あなたのプラットフォーム上の浮動小数点数です。

This threadには、これらの「マジックフロート」とそれを生成する方法がいくつかあります。

+0

IEEE 754のフロートのビット表現に依存し、 "あなたのプラットフォームでは"ではありません。 (現実のマシンには存在しない可能性のあるバイトオーダの問題をモジュロすることができます。)IMOこのようなコードの悪い唯一の問題は、不適切な型打ちです。この型は、ユニオンで置き換えられるべきです(スケッチですが、すべてのコンパイラによって意図的にサポートされます)。 'memcpy'(100%法的C)です。 –

+0

IEEE 754が必須の場合、 '__STDC_IEC_559__'定義の用途は何ですか? – Mat

+0

これは必須ではありませんが、C標準がどのように壊れていて、IEEE規格に準拠していない実装の浮動小数点数が許されているか、また浮動小数点演算に関してあなたが頼りにできるものは他にありません。浮動小数点を使用するために非IEEE数学システムに移植したいプログラムには大きな間違いがあります。 (当然ながら、IEEE以外の単一の実装でのみ使用するための移植性のないプログラムで使用することもできます) –

0

精度の限界は浮動小数点表現であり、printf()ではなく、誤った前提です。

また、単精度浮動小数点数は6桁の精度でしか保証されないため、「トリック」は自分自身をだますことになります。一般的にはうまくいかないでしょう。

10桁の浮動小数点数を使用する場合は、倍精度を使用する必要があります。これは15桁に適しています。

関連する問題