所以我有一个看起来像这样的函数:
float function(){
float x = SomeValue;
return x / SomeOtherValue;
}
在某些时候,此函数会溢出并返回一个非常大的负值。为了尝试准确地追踪这发生的位置,我添加了一个cout语句,以便函数看起来像这样:
float function(){
float x = SomeValue;
cout << x;
return x / SomeOtherValue;
}
它有效!当然,我通过使用双重完全解决了这个问题。但我很好奇为什么这个功能在我做的时候能正常工作。这是典型的,还是我可能在其他地方出现错误?
(如果有任何帮助,浮点数中存储的值只是一个整数值,而不是特别大的。我只是把它放在浮点数中以避免强制转换。)
答案 0 :(得分:18)
欢迎来到漂浮的精彩世界。您得到的答案可能取决于您编译代码的浮点模型。
这是因为IEEE规范与运行代码的硬件之间存在差异。您的CPU可能有80位浮点寄存器,可用于保存32位浮点值。这意味着当值保留在寄存器中时,精度远远高于强制存储器地址(也称为“归位”寄存器)。
当你将值传递给cout时,编译器必须将浮点写入内存,这会导致精度丢失和WRT溢出情况的有趣行为。
请参阅有关VC ++ floating point switches的MSDN文档。您可以尝试使用/ fp:strict进行编译,看看会发生什么。
答案 1 :(得分:3)
将值打印到cout不应该以任何方式改变参数的值。
但是,我看到过类似的行为,添加调试语句会导致值发生变化。在这些情况下,也许这个也可能是我的猜测是附加语句导致编译器的优化器行为不同,因此为您的函数生成不同的代码。
添加cout语句意味着直接使用x的vaue。没有它,优化器可以删除变量,因此改变计算的顺序,从而改变答案。
答案 2 :(得分:2)
顺便说一句,使用const
声明不可变变量总是一个好主意:
float function(){
const float x = SomeValue;
cout << x;
return x / SomeOtherValue;
}
除此之外,这将阻止您无意中将变量传递给可能通过非const
引用修改它们的函数。
答案 3 :(得分:1)
cout导致对变量的引用,这通常会导致编译器强制它将其溢出到堆栈。
因为它是一个浮点数,这可能导致它的值从它通常具有的双重或长双重表示中被截断。
调用任何带有指针或x引用的函数(非内联)最终会导致相同的行为,但如果编译器后来变得更聪明并且学会内联它,那么你将同样被搞砸了:)
答案 4 :(得分:0)
我不认为cout对变量有任何影响,问题必须在其他地方。