我正在调查当static_casting long double to double时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 double
的更高精度。上面示例中xStepL
的值为0.05000000000000000000067762635780344
。将此值转换回double
时,实际上又是0.050000000000000003
。但是,在使用gdb检查值时,它会打印以下内容:
(gdb) p xStep
$1 = 0.050000000000000003
(gdb) p static_cast<double>(xStepL)
$2 = 0.049999999999999996
知道结果有何不同?我其实希望它成为第二个。任何人都知道如何实现这一目标?
BTW,我使用的是GCC 4.3.4和GDB 7.2.50。
答案 0 :(得分:2)
这看起来像是gdb中的一个错误。
从long double
转换为double
的指令是fldt
(十字节浮点加载),后跟fstpl
(8字节浮点存储) 。当您执行精度降低的浮点存储时,它将围绕操作数,从0.05000000000000000000067762635780344
转到0.050000000000000003
。看起来gdb正在截断操作数,从0.05000000000000000000067762635780344
转到0.049999999999999996
。在浮点十六进制:
0x1.99999999999999999999ap-5 -> 0x1.999999999999ap-5 (gcc, correct)
0x1.99999999999999999999ap-5 -> 0x1.9999999999999p-5 (gdb, incorrect)
Discussion表示在最新版本的gdb(7.4.50)中已修复此问题。
答案 1 :(得分:1)
我认为问题在于static_casts
没有被调用相同的值。使用更高精度的寄存器值调用代码中的值,而从gdb调用的值将在内存中使用long double。我不确定编译器允许这样做的确切位置,但我猜这是一个 - 所以答案最终会因为一个elp而不同。