gpt4 book ai didi

linux - awk:为什么 awk 不能生成完整的渐进式 float 列表?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:19:59 25 4
gpt4 key购买 nike

    kitty@mypad:~$ awk 'BEGIN{for(i=0.01;i<=0.1;i=i+0.01) print i}'
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
kitty@mypad:~$ awk 'BEGIN{for(i=0.01;i<=0.2;i=i+0.01) print i}'
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
0.11
0.12
0.13
0.14
0.15
0.16
0.17
0.18
0.19

你看,对于 i<=k,当 k 为 0.1 时,它按预期生成,但是当 k 为 0.2 或 0.3 时,blabla,最后一个数字(0.2 或 0.3)不生成

为什么?

最佳答案

浮点不精确。 0.1、0.2 和 0.3 都不能用有限的二进制 float 精确表示——只有分母中具有 2 次幂的分数可以(直到一个点)——所以 awk 正在用近似值进行计算。有时这些会比您预期的大一点,有时小一点。当它们稍微大一点时,测试 i <= 0.2 比其他情况早一个迭代为假。

处理这个问题的通常方法是使用一个小的 epsilon 来抵消它,即

#                             v-- here
awk 'BEGIN{for(i=0.01;i<=0.2+1e-9;i=i+0.01) print i}'

请注意,epsilon 值的选择应使其小到不会篡改结果,但又大到足以抵消浮点舍入误差。在这种情况下,这意味着它应该比 0.01 小得多,并且假设 ieee-754 加倍,不小于,比如说,0.2 * 1e-12

后者的原因是由于 float 的尾数有限,在某些时候向数字添加一个非常小的 epsilon 不会改变它的值,即使 epsilon 不为零。例如,我得到

$ echo | awk '{ print 0.2 + 1e-30 == 0.2 }'
1

对一个好的 epsilon 值的估计并不是微不足道的,并且高度依赖于所讨论的计算,因此很难对后续问题给出一个普遍的答案。

请记住,这一磅盐必须按照这样的建议服用:为了简单比较像这样的简单计算的结果,您需要服用不少于 value * 1e-12 数量级的东西使用 double float (这是您通常拥有的)或 value * 1e-5 用于单精度 float 的计算。这是因为 ieee-754(每个人都使用)中 double float 的尾数是 53 个二进制数字长,大致对应于 16 个十进制数,而单精度 float 有 24 个二进制数/7 个十进制数。您希望安全地远离该边际两个或三个数量级。

对于复杂的计算,我没有一般的建议。有时舍入误差会累积,因此可能需要更大的 epsilon 来抵消它们。在某些计算中——例如通过差商进行数值微分——最佳 epsilon 值取决于您在计算商之前不知道的值,因为在减去两个 float 时必须考虑灾难性抵消的影响在分子中反对大割线步骤的数学含义。在这种情况下,您需要了解 float 和您正在处理的问题。

要了解浮点的工作方式以及对它们的期望,this 是一个很好的起点。

关于linux - awk:为什么 awk 不能生成完整的渐进式 float 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27989661/

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