我想我明白浮点数的精度意味着什么,因为你只能依赖于尾数中存储的内容。
如果我理解正确,如果您将0.000001 100000次添加到0,则可能会出现错误。
有没有办法防止此错误,预测它或通过在32位浮点数中使用较少的数字来缓解它?
编辑:例如,在星际争霸2中,只传达单位订单,而游戏状态则不然。仍然所有玩家都看到同样的事情。避免积累浮点错误,但是如何,成本或约束?
答案 0 :(得分:0)
当您在正确实现的浮点中执行单个操作并且舍入模式是舍入到最接近(最常见)时,错误最多为可表示数字之间距离的一半。这是因为,在舍入到最接近的模式中,操作返回最接近精确数学结果的可表示结果。 (这称为“正确的舍入”。)
这包括将数字(例如“0.000001”或“1e-5”)转换为浮点数等操作。但是,某些操作,特别是用于复杂操作(如正弦或对数)的库例程,通常并不总是返回正确的舍入结果(由于这样做很困难)。因此,在依赖错误界限之前,必须检查实现的规范。
32位IEEE 754浮点使用符号位,8个指数位(表示从-126到127的正常指数[2])和23个显式有效位。 (正确的术语是有效数。尾数是对数的小数部分。)完整有效数字有24位,因为有一个隐含的前导数(除了次正规数,低于2 -126 的数量级)。因此,可表示数字与下一个较高可表示数字之间的距离是前一位的值的2 -23 倍。当然,该值是2的最大功率,不大于数字。 (例如,对于5,前导位的值为4,因此最低有效位的值为4•2 -23 = 2 -21 。因此,如果精确的数学单次操作的结果大约为5,最大误差为2 -22 。)
执行多个操作时,错误很大程度上取决于所执行的操作和所涉及的值。必须进行仔细分析以确定误差范围。根据操作的不同,错误可能会合并并被放大,从而使错误变得无限。
请注意,如果您尝试添加0.000001 100,000次,则会出现两种错误。首先,0.000001在二进制浮点中不能完全表示,因此将该数字转换为浮点的操作存在错误。其次,每次添加都可能有舍入错误。
您还提到在不同的流程中维护相同的信息。这是一个与边界错误分开但又重叠的问题。如果进程在相同的平台上运行,则使用相同的硬件和库使它们使用相同的数据执行相同的操作可能并不难保持它们的同步。这是因为浮点错误通常不是随机的;对相同数据执行相同的操作将始终返回相同的结果。 (如果没有完全指定硬件或库行为并且允许依赖于不相关的数据,则可能会出现一些问题,尽管这往往比实际中的问题更具理论意义。)请注意,相同的平台意味着完全相同。像使用不同版本的相同库那样小的东西会产生不同的结果。
如果进程在不同平台上运行,则可能难以使它们保持同步。即使使用从相同源编译的软件运行,编译器也可以使用不同的浮点运算选项来实现高级语言。其中最臭名昭着的是使用比某些语言允许的高级语言要求更高的精度。
IEEE 754-2008标准的第11条有关于产生可重现的浮点结果的信息。计算平台可能无法提供必要的保证来支持这一点。
答案 1 :(得分:0)
使用多精度浮点库(二进制或十进制,具体取决于您是否始终准确表示十进制常量)或有理数的实现。
这是numerical stability的艺术。有基本原则,但在编程时记住它们并不总是那么容易。考虑solving二次方程的例子。
当您说“数字”时,您可能意味着十进制数字。关于二进制浮点的第一件事就是它用二进制表示,并且用十进制数字来思考它会引起混淆。
为了更直接地回答那个部分,隐藏一些精度只会掩盖问题,它不会修复它们。这几乎总是一个坏主意。
关于你的星际争霸2的例子,一个关于IEEE 754浮点的典型迷信是它不具有确定性,好像它可以在两台执行相同计算的计算机上给出不同的结果(比如网络游戏中的两个StarCaft 2客户端) )。那么,IEEE 754是确定性的。浮点计算与使用实数进行的相同计算略有不同,但只要每台计算机上的处理器正确实现IEEE 754,两次连续运行或运行相同二进制的两台不同计算机的计算总是相同的。标准(他们基本上做)。