【发布时间】: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