2

long double から double への static_casting 時の gcc と gdb の奇妙な動作に関する問題を調査しています。次のコードのようなものがあります。

const double xDelta = 60.0;
int xSplits = 3;
const long double xStepL = static_cast<long double>(xSplits) / xDelta;
const double xStep = static_cast<double>(xStepL);

基本的には 3/60 で割りますので、結果は 0.05 になるはずです。単純なdouble値で操作すると、 の値がxStepだった0.050000000000000003ので、より高い精度で 12 バイトを使用することにしましたlong doublexStepL上記の例の の値はでした0.05000000000000000000067762635780344。この値を にキャストし直すとdouble、実際には0.050000000000000003再びキャストされます。ただし、gdb で値を調べると、次のように出力されます。

(gdb) p xStep
$1 = 0.050000000000000003
(gdb) p static_cast<double>(xStepL)
$2 = 0.049999999999999996

結果が異なる理由は何ですか?本当は2本目でお願いしたいです。誰でもそれを達成する方法を知っていますか?

ところで、私は GCC 4.3.4 と GDB 7.2.50 を使用しています。

4

2 に答える 2

2

これは gdb のバグのようです。

long doublefrom からtoにキャストする命令doubleは、fldt(10 バイトの浮動小数点ロード) の後にfstpl(8 バイトの浮動小数点ストア) が続きます。低精度浮動小数点ストアを実行すると、オペランドが から に丸め0.05000000000000000000067762635780344られ0.050000000000000003ます。代わりに gdb がオペランドを切り捨て、 から0.05000000000000000000067762635780344に移動しているよう0.049999999999999996です。浮動小数点 16 進数の場合:

0x1.99999999999999999999ap-5 -> 0x1.999999999999ap-5 (gcc, correct)
0x1.99999999999999999999ap-5 -> 0x1.9999999999999p-5 (gdb, incorrect)

議論によると、これは gdb の最近のバージョン (7.4.50) で修正されています。

于 2012-08-02T14:01:06.930 に答える
1

問題はstatic_casts、同じ値で呼び出されていないことだと思います。コード内の値はより高い精度のレジスタ値で呼び出されますが、gdb から呼び出される値はメモリ内の long double を使用します。コンパイラがそれを許可されている正確な場所はわかりませんが、これは1つであると推測しているため、答えはelpごとに異なる場合があります。

于 2012-08-02T12:50:22.613 に答える