math - awk 浮点不精确
问题描述
我在 Awk 中遇到了无法解决的浮点不精确问题。有一个简单的解决方案吗?
这是我复制浮点不精确问题的示例 Awk 脚本。
BEGIN {
print "PREC = " PREC
print "OFMT = " OFMT
print "CONVFMT = " CONVFMT
a = 1.2 + 3.4
b = 8.9 - 4.3
print "a = " a
print "b = " b
if ( a == b )
print "a == b"
else
print "a != b"
c = 3.2 + 5.4
d = 9.8 - 1.2
print "c = " c
print "d = " d
if ( c == d )
print "c == d"
else
print "c != d"
}
这是上述脚本的输出。
PREC = 53
OFMT = %.6g
CONVFMT = %.6g
a = 4.6
b = 4.6
a != b
c = 8.6
d = 8.6
c == d
为什么 a != b 即使两者具有相同的值?然而, c == d 工作正常。
我假设 awk 有一些内部浮点不精确。仅供参考,我使用的是 Gawk 4.1.4。
我尝试了 PREC、OFMT 和 CONVFMT 的各种值,但找不到合适的值。
例如,将 OFMT 和 CONVFMT 更改为 %.6f:
PREC = 53
OFMT = %.6f
CONVFMT = %.6f
a = 4.600000
b = 4.600000
a != b
c = 8.600000
d = 8.600000
c == d
例如将 PREC 更改为 16:
PREC = 16
OFMT = %.6g
CONVFMT = %.6g
a = 4.6
b = 4.6
a != b
c = 8.6
d = 8.6
c == d
基本上,我希望在 BEGIN 中进行一些设置,而不是更改浮点算术和比较所在的每个表达式,因为我的实际 Awk 脚本比上面的示例要长得多。
例如,我宁愿不必为每个算术和比较表达式使用 sprintf,也不必在按 1e6 缩放后将每个输入数字转换为整数并将每个输出数字转换为 1e-6。这种方法将非常令人生畏。
仅供参考,输入文件中的浮点数最多有 6 个小数点,但它们可能没有小数点,即它们的范围从 0 到 6 个小数点。
谢谢您的帮助。
氢化物
解决方案
在这里,更高的精度对你不利。由于某些十进制值无法以二进制精确表示,因此您只是将数字等价的限制推向了无法满足的更高精度数字。
例如对于 53 位精度,你得到
1.2 => 1.199999999999999955591079014993738383054733
3.4 => 3.399999999999999911182158029987476766109467
8.9 => 8.900000000000000355271367880050092935562134
4.3 => 4.299999999999999822364316059974953532218933
a = 4.599999999999999644728632119949907064437866
b = 4.600000000000000532907051820075139403343201
a != b
3.2 => 3.200000000000000177635683940025046467781067
5.4 => 5.400000000000000355271367880050092935562134
9.8 => 9.800000000000000710542735760100185871124268
1.2 => 1.199999999999999955591079014993738383054733
c = 8.600000000000001421085471520200371742248535
d = 8.600000000000001421085471520200371742248535
c==d
我的建议是将 设置PREC
为更合理的值(基于您的输入数据精度)。我认为 10 是一个很好的折衷方案,代码更改最少。
'BEGIN{PREC=10; ...
注意。如果你问为什么c,d
匹配,请注意它们都是 0.2 的倍数的分数,而 a,b 是 0.3。
推荐阅读
- c# - 在 Xaml (UWP) 中格式化 TimeSpan
- python - 通过 Google Sheets API 和 Python 阅读 Sheet2
- ada - 更改构建目标编译文件的 gps 行为
- python-3.7 - ModuleNotFoundError:没有名为“队列”的模块
- wordpress - 文件权限恢复为 Wordpress 站点的只写
- node.js - 无法使用 DNS 访问服务
- android - Soft Keboard 在片段活动中覆盖 TextInputEditText
- r - 如何在R中按类别对df中的2乘2变量应用包含多元回归的函数?
- javascript - Firebase Firestore - 多个动态 where 查询
- c++ - 让对象知道在它创建的 show 函数中发生了什么