将double转换为float后的值不正确

我有一些C代码执行由gcc(gcc(GCC)4.4.4 20100726(Red Hat 4.4.4-13)编译的高精度算法。)计算的最终结果是双精度值,其值为622.07999995861189。我是将双人投掷到浮子上。

frequency_value =(float)current_freq;

其中current_freq是一个double,而frequency_value是一个float。强制转换后的frequency_value的值是622.080017。我希望在gdb中计算的值是622.079956

(gdb)p(float)current_freq $ 1 = 622.079956

任何人都可以解释gcc和gdb计算出的值之间的巨大差异。

浮子的精度远低于双精度; 你输了大约一半的数字。 所以充其量你会看到622.0799部分(四舍五入到622.0800)。 您看到的差异可能是由使用的舍入模式引起的。

以下是实际数字:

  • 双倍:622.0799999586118929073563776910305023193359375
  • 作为浮动:622.08001708984375(内部代表:1142654239)
  • 紧接在前的浮动:622.0799560546875(内部代表:1142654238)

内部表示是使用Java的Float.floatToIntBits生成的Float.floatToIntBits 。 您还可以使用Float.intBitsToFloat来获取浮点数。

浮点值通常以某种二进制格式存储在机器中,而不是以某种十进制格式存储。 因此,当您截断/舍入数字时,期望它将在其十进制数字中被截断/舍入是不合理的。 也就是说,期望622.07999995861189将变成必须以622.07999...开头的东西是不合理的622.07999... 一些前导十进制数字应该“存活”不变,但由于截断/舍入是在二进制表示上执行的(并且您在屏幕上看到的是将原始二进制格式转换为ASCII字符串的结果)很可能是受进程影响的十进制数字将远远超出预期。 在您的情况下,更改一直传播到点后的第二个数字。 这就是为什么你得到622.08...而不是622.07...

至于GDB的不同结果……很可能GDB的浮点计算模型与编译器的浮点计算模型不同。 例如,GDB可能会截断结果,而编译器则将其舍入。 或者编译器可能正在优化计算,这通常会导致稍微不同的结果。