当我在发布模式和调试模式下编译我的应用程序时,它会生成不同的浮点值。我发现的唯一原因是我保存了二进制跟踪日志,而发布版本中的日志与调试版本中的日志略有不同,看起来 32 位浮点值的底部两位大约有 1/2 不同案例。
您是否认为这种“差异”是一个错误,或者这种类型的差异是预期的。这是编译器错误还是内部库错误。
例如:
LEFTPOS and SPACING are defined floating point values.
float def_x;
int xpos;
def_x = LEFTPOS + (xpos * (SPACING / 2));
问题与 X360 编译器有关。
发布模式可能有不同的 FP 策略集。 根据您想要的优化级别,有不同的浮点运算模式。 例如,MSVC 具有严格、快速、精确的模式。
我知道在PC上,浮点寄存器是80位宽。 因此,如果计算完全在 FPU 内完成,您将受益于 80 位精度。 另一方面,如果将中间结果移出到普通寄存器并移回,它会被截断为 32 位,这会产生不同的结果。
现在考虑一下,发布版本将进行优化,将中间结果保留在 FPU 寄存器中,而调试版本可能会天真地在内存和寄存器之间来回复制中间结果 - 这就是你的行为差异。
我不知道X360上是否也会出现这种情况。
这不是一个错误。任何浮点运算都有一定的不精确性。在发布模式下,优化将更改操作的顺序,您将得到略有不同的结果。不过差异应该很小。如果它很大,您可能会遇到其他问题。
我帮助一位同事找到了一个编译器开关,该开关在发布版本与调试版本中不同,这导致了他的差异。
查看 /fp(指定浮点行为)。
除了其他人指出的不同浮点模式之外,SSE 或类似的向量优化可能会在发布时打开。 将浮点算术从标准寄存器转换为向量寄存器可能会对结果的低位产生影响,因为向量寄存器通常比标准浮点寄存器更窄(更少的位)。
不是错误。 这种差异是可以预料的。
例如,某些平台的浮点寄存器使用的位数多于内存中存储的位数,因此与存储到内存并从内存重新加载相比,将值保留在寄存器中可能会产生略有不同的结果。
这种差异很可能是由编译器优化引起的,编译器优化通常是在发布模式下完成的,而不是在调试模式下完成的。 例如,编译器可能会重新排序某些操作以加快执行速度,这可能会导致浮点结果略有不同。
所以,我想说这很可能不是一个错误。 如果你真的担心这个,请尝试在调试模式下打开优化。
就像其他人提到的那样,浮点寄存器比浮点数具有更高的精度,因此最终结果的精度取决于寄存器分配。
如果需要一致的结果,可以使变量可变,这会导致速度变慢、精度降低,但结果一致。
如果您设置了允许编译器重新排序浮点运算的编译器开关,-- 例如/fp:fast——那么显然这不是一个错误。
如果您没有设置任何此类开关,那么这是一个错误 - C 和 C++ 标准不允许编译器在未经您许可的情况下对操作进行重新排序。