gpt4 book ai didi

ruby - 为什么这个表达式会导致浮点错误?

转载 作者:数据小太阳 更新时间:2023-10-29 07:46:28 25 4
gpt4 key购买 nike

所以浮点运算是inexact但这并不能完全解释这里发生的事情:

[46] pry(main)> a=0.05
=> 0.05
[47] pry(main)> a=a*26.0/65
=> 0.02

所以在这里我们得到了我们所期望的,我们得到了正确的答案,世界一直在美丽地转动。但是我们后来重写了这个函数,当我们这样做的时候,我们将行 a=a*26.0/65 换成 a*=26.0/65 不是很好,我们少输入一个字符!让我们看看这对我们来说是如何解决的?

[48] pry(main)> a=0.05
=> 0.05
[49] pry(main)> a*=26.0/65
=> 0.020000000000000004
[50] pry(main)> 26.0/65
=> 0.4

说明a*=b和写a=a*b是不一样的。这似乎不是正常的 float 舍入错误,因为这些数字都不应该四舍五入为 float (尾数对于 26.0、26.0/65、65.0 中的每一个都应该足够长)

我确定幕后发生了一些微妙的事情,我想知道发生了什么?

最佳答案

浮点格式的有效位有足够的位来表示 26/65 是不正确的。 (“有效数”是首选术语。有效数是线性的。尾数是对数的。)

二进制 float 的有效位数是二进制整数。该整数根据指数缩放。要用二进制 float 表示 26/65,即 .4,我们必须将其表示为整数乘以 2 的幂。例如,.4 的近似值是 1•2-1 = .5。更好的近似值是 3•2-3=.375。更好的是 26•2-4 = .40625。

但是,无论您使用什么整数作为有效数或使用什么指数,这种格式都不可能正好是 .4。假设您有 .4 = f•2e,其中 fe是整数。那么 2/5 = f•2e,所以 2/(5f) = 2 e,然后 1/(5f) = 2e-1 和 5< i>f = 21-e。要做到这一点,5 必须是 2 的幂。它不是,所以你不能有 .4 = f•2e

在 IEEE-754 64 位二进制 float 中,有效数有 53 位。这样,最接近 .4 的可表示值是 0.40000000000000002220446049250313080847263336181640625,等于 3602879701896397•2-53

现在让我们看看你的计算。在 a=0.05 中,0.05 被转换为 float ,生成 0.05000000000000000277555756156289135105907917022705078125。

a*26.0/65 中,a*26.0 首先被评估。精确的数学结果四舍五入到最接近的可表示值,得到 1.3000000000000000444089209850062616169452667236328125。然后除以 65。答案再次四舍五入,得到 0.0200000000000000004163336342344337026588618755340576171875。当 Ruby 打印这个值时,它显然认为它足够接近 .02,所以它可以只显示“.02”而不是完整的值。这是合理的,因为如果将打印值 .02 转换回 float ,您将再次获得实际值 0.0200000000000000004163336342344337026588618755340576171875。所以“.02”在某种意义上是 0.0200000000000000004163336342344337026588618755340576171875 的一个很好的代表。

在您的替代表达式中,您有 a*=26.0/65。在此,首先评估 26.0/65。这将产生 0.40000000000000002220446049250313080847263336181640625。 这与第一个表达式不同,因为您以不同的顺序执行了操作,因此舍入了不同的数字。第一个表达式中的值可能会向下舍入,而这个不同的值,因为它碰巧落在相对于浮点表示的值的位置,向上舍入。

然后该值乘以a。这会产生 0.02000000000000000388578058618804789148271083831787109375。请注意,此值比第一个表达式的结果更远离 .02。您的 Ruby 实现知道这一点,因此它确定打印“.02”不足以准确表示它。相反,它会显示更多数字,显示 0.020000000000000004。

关于ruby - 为什么这个表达式会导致浮点错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20101146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com