9

所以我有一个看起来像这样的函数:

float function(){
    float x = SomeValue;
    return x / SomeOtherValue;
}

在某些时候,这个函数溢出并返回一个非常大的负值。为了尝试准确追踪发生这种情况的位置,我添加了一条 cout 语句,使函数看起来像这样:

float function(){
    float x = SomeValue;
    cout << x;
    return x / SomeOtherValue;
}

它奏效了!当然,我通过使用 double 完全解决了这个问题。但是我很好奇为什么当我计算它时该功能可以正常工作。这是典型的,还是我在其他地方遗漏了一个错误?

(如果有帮助的话,存储在浮点数中的值只是一个整数值,并不是特别大的值。我只是将它放在浮点数中以避免强制转换。)

4

5 回答 5

18

欢迎来到浮点的奇妙世界。您得到的答案可能取决于您编译代码时使用的浮点模型。

发生这种情况是因为 IEEE 规范和运行代码的硬件之间存在差异。您的 CPU 可能有 80 位浮点寄存器,用于保存 32 位浮点值。这意味着值保留在寄存器中时的精度要比强制到内存地址时的精度高得多(也称为“归位”寄存器)。

当您将值传递给 cout 时,编译器必须将浮点写入内存,这会导致精度丢失和有趣的行为 WRT 溢出情况。

请参阅有关 VC++浮点开关的 MSDN 文档。您可以尝试使用 /fp:strict 进行编译,看看会发生什么。

于 2008-09-08T03:43:10.770 回答
3

将值打印到 cout 根本不应该以任何方式更改参数的值。

但是,我看到了类似的行为,添加调试语句会导致值发生变化。在这些情况下,可能这也是我的猜测是附加语句导致编译器的优化器表现不同,因此为您的函数生成不同的代码。

添加 cout 语句意味着直接使用 x 的值。没有它,优化器可以删除变量,从而改变计算的顺序,从而改变答案。

于 2008-09-08T03:20:31.463 回答
2

顺便说一句,使用以下方法声明不可变变量总是一个好主意const

float function(){
    const float x = SomeValue;
    cout << x;
    return x / SomeOtherValue;
}

除其他外,这将防止您无意中将变量传递给可能通过非const引用修改它们的函数。

于 2008-09-08T16:16:46.653 回答
1

cout 导致对变量的引用,这通常会导致编译器强制将其溢出到堆栈中。

因为它是一个浮点数,这可能会导致它的值从它通常具有的双精度或长双精度表示中截断。

调用任何接受指针或引用 x 的函数(非内联)最终会导致相同的行为,但如果编译器后来变得更聪明并学会内联它,你同样会被搞砸:)

于 2010-08-31T10:07:05.090 回答
0

我认为 cout 对变量没有任何影响,问题必须出在其他地方。

于 2008-09-08T03:21:04.817 回答