私はしばしば、コマンドラインプログラム "printf" を使って、C stdioライブラリ関数が何をするかをテスト/予測しました。printf( "%。17g n"、.1)はどうすれば印刷できますか?
しかし、私が最近発見したことは(それ以上?)を動作しません - 少なくとも最近のLinux/Ubuntuのリリースで、 コマンドラインのprintf(組み込みのbashと/ usr/binに両方/ printf) は、C関数とは異なる結果を与えることがあります。そのような(明らかに) のpython、perlの、gnuplotの、または実際のCプログラムとして、私は 、C関数が何をするか確認したい場合、私は実際にCの関数を呼び出すいくつかの他のプログラムを実行しなければならないことを意味
。ここで
は、Linux上で、デモです:いくつかの他のプラットフォームで
bash$ uname -srvmpio
Linux 3.13.0-95-generiC#142-Ubuntu SMP Fri Aug 12 17:00:09 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
bash$ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
bash$ type printf
printf is a shell builtin
bash$ printf "%.17g\n" .1
0.1
bash$ /usr/bin/printf "%.17g\n" .1
0.1
bash$ python -c 'print "%.17g" % .1'
0.10000000000000001
bash$ perl -e 'printf("%.17g\n", .1);'
0.10000000000000001
bash$ gnuplot -e 'print sprintf("%.17g", .1)'
0.10000000000000001
bash$ echo -e '#include <stdio.h>\nint main(){printf("%.17g\\n",.1);}' | gcc -xc - -o /tmp/printf_.1 && /tmp/printf_.1
0.10000000000000001
、例えば最新のMacBook、それらはすべて(私は常に正しい答えだと思ってきました)「0.10000000000000001」 を与える:
bash$ uname -srvmp
Darwin 15.6.0 Darwin Kernel Version 15.6.0: Thu Jun 23 18:25:34 PDT 2016; root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64 i386
bash$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
bash$ type printf
printf is a shell builtin
bash$ printf "%.17g\n" .1
0.10000000000000001
bash$ /usr/bin/printf "%.17g\n" .1
0.10000000000000001
私は、もちろん上記のコマンドがないことに驚いと失望していますすべて特定のプラットフォーム内で全く同じ出力を提供します。 私の質問です:いくつかの公式の仕様によると、正しい答えが1つあります、とにかく、バグレポートを提出する必要がありますか?
一部背景の事実:Cで
.1は、数学的に値正確にIEEE倍精度浮動小数点数 、意味:
x = 0.1000000000000000055511151231257827021181583404541015625
を、隣接する表現可能な値は、次のとおり
x- = 0.09999999999999999167332731531132594682276248931884765625
x+ = 0.10000000000000001942890293094023945741355419158935546875
したがって、文字列表現「0.10000000000000001」と「0.1」は両方とも非ロスであるため、 それらが両方とも他の倍精度値よりもxに近いこと。 つまり、いずれかの文字列が指定されている場合、妥当な文字列から二重への変換関数は、 xを生成します。だから両方の答えはこの意味で同じように良いです。
ただし、0.10000000000000001は0.1よりxに近い。 私はいつも "0.10000000000000001"が正解であることを意味していると思っていましたが、 ですが、今は分かりません。実装依存の詳細なのでしょうか? 17どのような場合に使用される数字の右の数である、numeric_limitsのため マニュアルを参照してください理由の説明について
:: max_digits10:
http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2005.pdf
@ user3386109 "help printf"は、/ usr/bin/printfが行うことに加えて、いくつかの拡張機能を追加しました。 "man printf"は、/ usr/bin/printfはC printfが何をするかを示します。 C printfが正しい答えを持っていれば、それらはすべて確実に答えます。もしそうでなければ、私は同じ回答を与えるなら、本当に役に立つだろうという微妙な議論をしなければなりません。 )。 –
単精度値(float)を比較しようとするべきではありません。正確ではありません。 –
@ user3386109 "stdio"タグを削除して "bash"を追加しました。私はそれに同意しない。私の見解では、この質問は実際にはbashに関するものではありません。 bashの振る舞いは/ usr/bin/printfに委ねられています。これは私がよりよく振る舞い、指定されたプログラムです。 stdioはbashよりも関連性の高いタグです。 –