我在C ++中有一些图像处理代码,它使用霍夫变换算法计算渐变并在其中找到直线。该程序使用浮点数进行大部分计算。
当我在两台不同的计算机上的同一图像上运行此代码时,一台Pentium IV运行最新的Fedora,另一台运行Core i5最新的Ubuntu,32位,我的结果略有不同。例如。我对一台机器上的某些变量和另一台机器上的1.3457f进行了一些长时间的计算1.3456f。这是预期的行为还是应该在我的程序中搜索错误?
我的第一个猜测是,我正在访问一些未初始化或超出范围的内存但是我确实通过valgrind运行程序并且它找不到任何错误,同时在同一台机器上运行多次总是给出相同的结果。
答案 0 :(得分:11)
这并不罕见,它取决于您的编译器,优化设置,数学库,CPU,当然还有您正在使用的算法的数值稳定性。
您需要很好地了解自己的准确度要求,如果不满足这些要求,则可能需要查看算法,例如:考虑在需要时使用double而不是float。
答案 1 :(得分:4)
有关为什么给定源代码可能不会在不同计算机上产生相同输出的背景信息,请参阅What Every Computer Scientist Should Know About Floating-Point Arithmetic。我怀疑这是因为你的代码有任何不足,除非它以非确定的方式执行聚合,例如。通过集中整理来自多个线程的计算结果。
浮点行为通常可以根据编译器选项进行调整,甚至可以调整到不同CPU的级别。检查编译器文档,看看是否可以减少或消除差异。在Visual C ++上(例如),这是完成via /fp。
答案 2 :(得分:3)
是否由于称为机器epsilon的声音?
http://en.wikipedia.org/wiki/Machine_epsilon
flaoting-point数量有限制。事实上,浮点数不能精确地表示所有实数,并且浮点运算不能精确地表示真正的算术运算,这会导致许多令人惊讶的情况。这与计算机通常代表数字的有限精度有关。
答案 3 :(得分:3)
基本上,相同的C ++指令可以编译为不同的机器指令(即使在相同的CPU上,当然也在不同的CPU上),这取决于很多因素,并且相同的机器指令可能会导致不同的低级CPU操作取决于很多因素。理论上,这些应该在语义上是等价的,但是对于浮点数,有边缘情况它们不是。
阅读"The pitfalls of verifying floating-point computations" by David Monniaux了解详情。
答案 4 :(得分:1)
我也会说这很常见,可能不是你的错。
我过去花了很多时间试图找出同样的问题。
我建议您使用decimal
代替float
和double
,只要您的数字不是指科学计算,而是指价格,数量,汇率等值。
答案 5 :(得分:1)
不幸的是,这是完全正常的。
有些库可以在任何地方产生相同的结果 - 请参阅http://www.mpfr.org/作为示例。但是性能成本是巨大的,除非完全相同的结果是最重要的重要标准,否则它可能不值得。
我实际上编写了一个闭源库,它在整数单元中实现了浮点数学,以便使浮点数在不同编译器的多个平台(Intel,AMD,PowerPC)上提供相同的结果。我们有一个应用程序,如果浮点结果变化,根本无法运行。不过,这是一个相当大的挑战。如果我们可以再做一次,我们只是在定点设计原始应用程序,但当时重写的代码太多了。
答案 6 :(得分:0)
这是浮动的内部表示之间的差异,结果略有不同,或者浮动打印到屏幕的方式可能不同?我怀疑这是你的错......