2012-02-29 12 views
1
#include <stdio.h> 
#include <wchar.h> 
int main() 
{ 
    double f = 1717.1800000000001; 
    wprintf(L"double  %.20G\n", f); 
    return 0; 
} 

出力(以下予想):GCC二重のprintf精度 - 間違った出力

double  1717.1800000000000637 
double  1717.1800000000001 

これはUbuntuの11.10 x64である(しかし、32ビット用にコンパイルする場合)。

私が解決しようとする問題は、Windowsではコードのように数字を出力し、移植性の問題ではWindowsのように動作するように低レベルの書式設定(swprintf)を行う必要があるということです。

+0

1717.1800000000001は正確には二重表現ではないので、 'f'の値の近くでしか値を取得できません。 fに格納される値は、正確に1717.180000000000063664629124104976654052734375です。問題は20がリクエストされたにもかかわらず、ウィンドウが17桁の有効数字だけを出力するようになったことです(既知のバグ、AFAIKはバグデータベースのどこかにあります)。フィールドの長さを(17のような)正当な値に制限できない場合は、このバグを模倣するためのラッパーが必要です。 – hirschhornsalz

+0

これは非常に興味深いことですが、正確なバグを覚えていますか?これは私が必要とするもので、Linux版をそのバグがあってもWindowsのように動作させるためです。 – queen3

+0

実際には.20の代わりに.17を設定しました。そして、linux/windowsは完全に互換性があります。あなたがあなたのコメントを私が喜んでそれを受け入れる答えを変更する場合。しかし、あなたが正確なバグのリンクを見つけることができれば、それはさらに役に立つでしょう。 – queen3

答えて

2

1717.1800000000001は、正確にはdoubleと表現できないため、fの中で値を取得するだけです。 fに格納される値は、正確に1717.180000000000063664629124104976654052734375です。

問題が発生したのは、ウィンドウが17桁しか出力されないのに対し、20個がリクエストされました(既知のバグ、AFAIKはバグデータベースのどこかにあります)。

フィールド長を("%.17G"のような)正常な値に制限できない場合は、このバグを模倣するためのラッパーが必要です。

+0

このバグは次のように見えます:http://connect.microsoft.com/VisualStudio/feedback/details/329278/printf -sprintf-do-not-print-significant-significant-digits-for-binary-fractions – queen3

+2

@ queen3:はい、それはバグレポートです(書きました)。詳細については、私の記事http://www.exploringbinary.com/print-precision-of-dyadic-fractions-varies-by-language/を参照してください。 –

+0

@ queen3:よく目に付きます。そのバグの背後にある物語を見て興味深い。 – hirschhornsalz

1

wprintf機能はgccではなく標準Cライブラリで実装されています。

番号1717.1800000000001は、浮動小数点の後に13桁の数字を持ちます。ただし、64ビットバイナリ浮動小数点形式では正確な表現はありません。

フォーマット"%.20G"は、1717.1800000000000637の桁数である有効桁20桁を出力する必要があります。したがって、この出力は期待どおりです。 Windows標準のCライブラリは、書式を異なる方法で処理するか、不正確な丸めを行います。

一方、"%f"形式を使用すると、浮動小数点の後に特定の桁数を要求できます。 "%.13f"は、浮動小数点数の後に出力を正確に13桁に丸め、期待通りに1717.1800000000001を出力します。

0

あなたの予想される出力は、フォーマット文字列と競合します。 "%.20G"は20桁の有効数字が必要なことを意味し、それはあなたが得ているものです。予想される出力のように17桁の有効数字が必要な場合は、 "%.17G"を使用します。

0
double f = 1717.1800000000001; 

このコード行は正確に実行できません。定数の精度は17桁で、倍数は15.9です。

+0

OPによって与えられた値を正確に表すことはできません。しかし、残りの答えは間違っています。これはかなり簡単に表示できます。 'f = 1717.180000000000063664629124104976654052734375'という行は、もっと数字が入っていますが、正確に実行されます。 – hirschhornsalz

+0

しかし、正確に実行できないコード行にはありませんか?そして、二重表現は53ビットしか持たず、その値はもっと必要なので、1717.180000000000063664629124104976654052734375のバイナリ表現を私に見せる必要があります。 – EJP

+0

いいえ、正確に53ビット必要です。やってみなよ。任意の長さの演算(gpのような)を処理できるcalcluatorで実行する "15466982416256137216.0/2^53" – hirschhornsalz

関連する問題