【问题标题】:Is it possible to force truncation when instantiating Boost cpp_dec_float from a floating point value?从浮点值实例化 Boost cpp_dec_float 时是否可以强制截断?
【发布时间】:2021-08-26 06:50:40
【问题描述】:

我们正在编写软件,对具有 8 个固定十进制数字(. 之后的 8 个十进制数字)的数字进行算术运算。

我们曾多次被诸如double 等内置浮点类型的有限精度所困扰,主要是在相等比较(在小数点后第 17 位左右失败)。所以我们尝试改用一些固定精度十进制类型。

从它的文档来看,cpp_dec_float 应该是这样一种类型。 所以我们用using Decimal = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<8>>;替换了我们的using Decimal = double

如果我们从字符串实例化Decimal,一切都会正常工作,但是从浮点字面量实例化它时会出现复杂情况:

assert(Decimal{0.001} == Decimal{"0.001"});

上述断言失败,因为左侧的 Decimal 实例似乎带有用于初始化它的字面量的不精确表示,即使这个 epsilon 远远超出了所要求的精度 8

有没有办法获得“在实例化时截断”行为,所以上述断言得到满足? (理想情况下,该解决方案不需要触摸发生此类实例化的所有调用站点)

【问题讨论】:

  • 不确定这里出了什么问题。我希望浮点值截断为 0.001。但是用浮点小数初始化这种类型是generally unreliable。您可以通过除法来避免浮点,例如Decimal{1}/1000 或使用诸如 CNL 的 ""_cnl (example) 之类的 UDL。
  • 感谢您的评论。我还期望 cpp_dec_float 截断到要求的精度,但显然不是这样。 (我在您提供的链接中没有看到对cpp_dec_float 的任何引用)。实际上,避免浮点的一种简单方法是从字符串初始化,例如Decimal{"0.001"},但我希望有一个 drop-in 解决方案,不需要触及已经初始化 @ 的现有呼叫站点987654336@ 来自double 变量和文字。
  • 不准确:print("%1000.1000f\n") % (0.001) ==> 0.0010000000000000000020816681711721685132943093776702880859375000...
  • @Andrew 您能否详细说明什么是不准确的,以及您的代码语句说明了什么?
  • @Ad N :不精确的浮点数是无法准确表示为浮点数的浮点数。准确的0.001是0.00100000000000000000000000000000000000000000 ....但它不能存储这样的浮动,因为这段代码声明,强制打印,显示更精确的说明:“打印(”%100.100f \ n“)%(0.00100000000000000000000000000000000000000000 )”。该语句返回:“0.0010000000000000000208166817117216851329430937767028808593750000000000000000000000000000000000000000”,这不完全是0.001。

标签: c++ boost floating-point fixed-point boost-multiprecision


【解决方案1】:

这或许可以解释:

0.001 as a 32 bit float is exactly:
0.0009999999310821295
    12345678 are the 8 digits of accuracy
0.0009999999 is 0.001 as a 32 bit float rounded to the 8 digits of accuracy
0.0010000000 is 0.001 truely ecarately 

VS 7 bits of accuracy:
0.0009999999310821295
    1234567
0.001000000
0.001000000

【讨论】:

    猜你喜欢
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    相关资源
    最近更新 更多