我有一段简单的代码,可以使用浮点运算。 循环中很少有乘法,除法,exp(),减法和加法。 当我在不同的平台(如PC,Android手机,iPhone)上运行相同的代码时,我得到的结果略有不同。 结果在所有平台上几乎相同,但差异非常小 - 通常为浮点值的1/1000000。
我想原因是有些手机没有浮点寄存器,只是用整数模拟这些计算,有些手机有浮点寄存器,但有不同的实现。 这里有证明:http://christian-seiler.de/projekte/fpmath/
有没有办法强制所有平台产生一致的结果? 例如,一个好的&快速开源库,用整数(软件)实现浮点机制,因此我可以避免硬件实现的差异。
我需要精确一致性的原因是避免计算层之间的复合错误。 目前,这些复合错误会产生明显不同的结果。 换句话说,我并不在乎哪个平台的结果更正确,而是希望强制一致性以便能够重现同等行为。例如,在手机上发现的错误更容易在PC上调试,但我需要重现这种确切的行为
答案 0 :(得分:2)
一种相对广泛使用的高质量软件FP实现是MPFR。但是,它比硬件FP慢很多。
当然,这不会解决您的算法在复合错误中遇到的实际问题,它只会使它在所有平台上产生相同的错误。如果可行的话,可能更好的方法是设计一种对FP算术中的小差异不敏感的算法。或者,如果你使用MPFR路径,你可以使用更高精度的FP类型,看看是否有帮助,不需要限制自己模拟硬件单/双精度。
答案 1 :(得分:1)
32位浮点数学,对于给定的计算,最多在16777216中具有1的精度(1 in 2 24 )。诸如exp
之类的函数通常被实现为一系列计算,因此可能会出现更大的错误。如果连续进行多次计算,则错误将增加并相乘。通常,float
具有大约6-7位精度。
正如一条评论所说,检查舍入模式是一样的。大多数FPU都有#34;到最近的#34; (rtn),"舍入到零" (rtz)和" to to even" (rte)模式,你可以选择。不同平台上的默认值可能会有所不同。
如果对相当大的数字执行相当小的数字的加法或减法,由于数字必须被标准化,因此这些操作会产生更大的错误。
标准化意味着移动使得两个数字都排成小数位 - 就像你在纸上做的那样,你必须填写额外的零来排列你添加的两个数字 - 但当然在纸上你可以添加12419818.0与0.000000001,最终得到12419818.000000001,因为纸张具有尽可能多的精度,你可以打扰。在float
或double
中执行此操作将导致与之前相同的数字。
pi
1000个数字,或何时例如,您想要计算远大于64或128位的范围内的素数。
它可以解决使用这样一个库的问题,但它会很慢。
更好的选择,从float
移动到double
应该有类似的效果(double
有53位尾数,而32位浮点数则为23,所以尾数中位数的两倍多。并且应该仍然可以作为任何合理的最新ARM处理器中的硬件指令使用,并且因此相对较快,但不如float
快(FPU可从ARMv7获得 - 这当然是你在iPhone中找到的 - 至少来自iPhone 3和中高端Android设备 - 我设法发现三星Galaxy ACE有一个ARM9处理器[1997年首次推出] - 所以没有浮点硬件。)