首先,对不起,如果这个问题看起来很“傻”,因为我是MPFR的新手,大声笑。
我有两个精度为1024的mpfr_t
变量,它们中存储的值分别为0.2和0.06。
但是当我添加这些变量时,事情就出错了,结果(也是mpfr_t
变量)的值为0.2599999 ...
这很奇怪,因为MPFR库应该保持精度(不是吗?)。
您能帮我吗?非常感谢,非常感谢。
答案 0 :(得分:0)
MPFR编号以二进制(基数2)表示。在此系统中,唯一可以精确表示的数字的形式为 N ·2 k ,其中 N 和 k 是整数。 0.2 = 1/5或0.06 = 3/50都不具有这种形式,因此它们的近似值会有一些小误差。当您添加这些变量时,您会看到此错误的后果(在加法运算中可能还会出现另一个错误,因为在二进制中,这些数字具有许多非零数字,与十进制不同)。
这与Is floating point math broken?
中描述的问题相同。编辑:
要回答评论“是否有办法避免这种情况?”的问题,不可以,除了非常特殊的情况外,实际上没有办法避免这种情况。例如,如果您所有的数字(每个中间操作的输入和结果)都是十进制数字,可以用足够小的数字表示,那么您可以使用十进制算术(但是MPFR不能这样做)。计算机代数系统在某些情况下可能会有所帮助。还有iRRAM ...我待会儿再讲。
但是,有一些解决方案试图隐藏带有数字错误的问题。您需要估计计算值上的最大可能误差。通过错误分析,您可以获得严格的界限,但这可能很困难或需要时间。请注意,严格的界限通常是悲观的,但是如果您使用任意精度(例如,使用MPFR),那么问题就不那么严重了。可以使用区间算法动态地进行分析(仍然悲观,甚至更糟)。但是也许一个简单的估计就足够了。估算出最大误差后:
注意:MPFR不会为您这样做。但是您可以编写代码来考虑这些规则。
基于MPFR的iRRAM软件包可以严格地跟踪错误(例如使用间隔算术),并且自动在注意到精度的情况下以更高的精度自动重做所有计算太低了。但是,如果某些数学结果是不连续点,则iRRAM将无济于事。特别是它不能提供严格的平等测试。
最后,我建议您看看Goldberg的论文What Every Computer Scientist Should Know About Floating-Point Arithmetic,尤其是 cancellation 的概念。