awk中的数学 - 浮点数的意外格式化 - 精度损失

时间:2017-02-11 21:33:12

标签: awk

我想在awk中做一些简单的数学

user@lab-client:~$ awk '{ram=(1.8 * 1024) * 1024; print ram}'

1.88744e+06

所以我认为这意味着这个数字太大而无法存储在变量“ram”

总人数为:1887436.8

让我们尝试将该数字存储在变量

user@lab-client:~$ awk '{ram=1887436.8; print ram}'

1.88744e+06

再次相同。但是,如果我们摆脱“。”呢?

user@lab-client:~$ awk '{ram=18874368; print ram}'

18874368

进一步的测试显示,当点在数字中时,它不能超过6位

user@lab-client:~$ awk '{ram=188743.68; print ram}'

188744

所以它不是一个太大的数字,它是一个让人眼花缭乱的点。我怎么能绕过这个?

2 个答案:

答案 0 :(得分:2)

你可以用printf控制小数点的数量,最后虽然由于浮点表示而数字不会很大

例如

awk 'BEGIN{for(i=5;i<20;i++) printf "%."i"f\n", 1./3}'

0.33333
0.333333
0.3333333
0.33333333
0.333333333
0.3333333333
0.33333333333
0.333333333333
0.3333333333333
0.33333333333333
0.333333333333333
0.3333333333333333
0.33333333333333331
0.333333333333333315
0.3333333333333333148

答案 1 :(得分:2)

补充karakfa's helpful answer

除了使用printfsprintf显式数字格式外,您还可以更改awk 默认值浮点数字格式,通过内置变量OFMT
请注意,它适用于整数

OFMT默认为%.6g ,这意味着任何浮点数都会舍入为6位有效数字,而以7开头的指数则以科学计数法表示。< / p>

计算结果1887436.8 - 其中 8 有效数字 - 因此表示为1.88744e+06,即带有6位有效数字的科学记数法。

以下示例将OFMT设置为%1.f,以便在默认情况下输出所有带小数点后1位的浮点数:

$ awk -v OFMT='%.1f' 'BEGIN {ram=(1.8 * 1024) * 1024; print ram}'
1887436.8

但请注意,OFMT 不适用于以下情况:

  • 如果在字符串连接中使用浮点数

    $ awk -v OFMT='%.1f' 'BEGIN { print "result: " 1 / 3 }'
    result: 0.333333
    
    # Workaround: Use `sprintf()` with OFMT
    awk -v OFMT='%.1f' 'BEGIN { print "result: " sprintf(OFMT, 1 / 3) }'
    result: 0.3
    
  • 如果文字可以解析作为整数 - 即使看起来像浮点数一样:

    $ awk -v OFMT='%.1f' 'BEGIN { print 1.000 }'
    1
    

警告awk中的数字转换和格式有许多细微之处,尤其是因为浮点数的精度有限(awk总是如此) ISO C double 类型)。