计算幅度<1且幅度>1时的精度损失
Posted
技术标签:
【中文标题】计算幅度<1且幅度>1时的精度损失【英文标题】:Accuracy loss when calculating magnitudes <1 with magnitudes >1 【发布时间】:2014-05-31 00:37:17 【问题描述】:我正在测试构造 gmp_float
的字符串。
这段代码
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <iostream>
using namespace boost::multiprecision;
typedef number<gmp_float<15>> mp_type;
int main()
mp_type total("1.01");
cout << total.str(0) << endl;
mp_type first_addition(".01");
cout << first_addition.str(0) << endl;
total += first_addition;
cout << total.str(0) << endl;
打印
1.01
0.01
1.01999999999999999998
为什么?我进行了更多测试,在这种特殊情况下,只要一个数字的大小是 >0 和 1,那么操作是什么并不重要。
从上面的链接
不可能将这种类型的对象往返于字符串之间并返回完全相同的值。这似乎是 GMP 的限制。
是否还有其他区域会丢失准确性?
【问题讨论】:
即使gmp_float
被宣传为具有“更高的精度”,我怀疑精度是无限的。尤其是在0
附近。
Here我已经为那些感兴趣的人复制了这个问题。
离 [0.0,1.0] 越远,浮点数越容易受到精度问题的影响。如果您希望在可表示的整个值范围内具有相同的精度,请改用定点。顺便说一句,您甚至不能将 0.01 表示为浮点中的二次幂。
【参考方案1】:
Boost Multiprecision 也有十进制浮点数:
查看 Live On Coliru 打印:
clang++ -std=c++11 -Os -Wall -pedantic main.cpp && ./a.out
1.01
0.01
1.02
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
using namespace boost::multiprecision;
using std::cout;
using std::endl;
typedef cpp_dec_float_50 mp_type;
int main()
mp_type total("1.01");
cout << total.str(0) << endl;
mp_type first_addition(".01");
cout << first_addition.str(0) << endl;
total += first_addition;
cout << total.str(0) << endl;
【讨论】:
【参考方案2】: GMP 中的mpf_t
是一个 二进制 浮点数。 0.01
不能精确地表示为任何有限精度的二进制浮点数。
将0.01
更改为0.125
和1.01
更改为1.125
使格式化输出看起来很好。这是因为0.125
和1.125
可以精确地表示为具有至少 8 位有效数字的二进制浮点数。
【讨论】:
我相信gmp_float
只是包装mpf_t
。我使用的mpf_class
只是包装了mpf_t
。
@Gracchus:为什么?你为什么关心十的幂?
@Gracchus:恶心。用美分或任何被测量的最小货币单位来衡量一切。或者如果你真的需要的话,可以使用一些十进制浮点数。如果您选择理解二进制浮点,它仍然是您的朋友。
@Gracchus:存在十进制浮点格式和库。我不认为 gmp 有一个。我没有使用它们的经验,所以我不能推荐使用哪个。
+1 提供信息,我已经用适当的提升解决方案回答了以上是关于计算幅度<1且幅度>1时的精度损失的主要内容,如果未能解决你的问题,请参考以下文章