【问题标题】:Accuracy loss when calculating magnitudes <1 with magnitudes >1计算幅度<1且幅度>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 表示为浮点中的二次幂。

标签: c++ string boost gmp arbitrary-precision


【解决方案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.1251.01 更改为1.125 使格式化输出看起来很好。这是因为0.1251.125 可以精确地表示为具有至少 8 位有效数字的二进制浮点数。

    【讨论】:

    • 我相信gmp_float 只是包装mpf_t。我使用的mpf_class 只是包装了mpf_t
    • @Gracchus:为什么?你为什么关心十的幂?
    • @Gracchus:恶心。用美分或任何被测量的最小货币单位来衡量一切。或者如果你真的需要的话,可以使用一些十进制浮点数。如果您选择理解二进制浮点,它仍然是您的朋友。
    • @Gracchus:存在十进制浮点格式和库。我不认为 gmp 有一个。我没有使用它们的经验,所以我不能推荐使用哪个。
    • +1 提供信息,我已经用适当的提升解决方案回答了
    猜你喜欢
    • 2013-06-02
    • 1970-01-01
    • 2017-01-21
    • 2022-11-12
    • 2019-11-25
    • 2012-12-06
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多