如何转换cpp_dec_float_50至cpp_int?关于浮点一般?

时间:2013-04-16 09:38:19

标签: c++ boost floating-point

我的基本目标是减去两个应该是等效的浮点数。 考虑一下: -

float x=1;
float a=x/30-x/40;    
float b=x/30;
b-=x/40;
std::cout<<a-b<<std::endl;

我应该零。但我没有。相反,我得到了一个非常小的数字大约10 ^( - 10)。

现在,有两种选择: -

首先,我想到使用理性表达式而不是分数(处理分子和分母),然后将最终的有理表达式转换为分数。我通过Boost.rational做到了这一点。我使用cpp_int来存储分子和分母,因为分子和分母可能变得很大。它工作正常。但问题是我正在制作的节目需要花费很多时间。我认为这是因为必须处理大整数。

其次,我被建议尝试定点算术。我不是很擅长。所以,我不确定定点算法是否会给出正确的答案?我在想的是这个 - &gt; 假设我希望我的减法结果正确到达第50个精度。所以我通过将其乘以10的适当幂来得到小数点左边的50位数。删除小数部分并将其转换为cpp_int。我用两个花车做这个。然后对这些cpp_int执行减法。 两个问题: - 首先,我无法将cpp_float_dec_50转换为cpp_int。 Boost不允许直接进行这种(有损)转换。 其次,我对这种方法毫无信心。

所以,最后两个问题: - 如何将cpp_float_dec_50转换为cpp_int? 到目前为止在问题中呈现的上下文中哪种方法最好的两个减去两个浮点数?

感谢。对不起,如果任何这些都是高度愚蠢或愚蠢的问题。 我还在学习。

1 个答案:

答案 0 :(得分:2)

您需要决定是否需要精确的表示。如果10 ^ -10太大的错误,你可能想要完全正确。我可以说固定点表示本身并不比内置类型更好;如果你扩展它的精度和能力,你会得到一个多精度库:)。

我可以推荐boost::multiprecision,并且发现它相当简单,但因为它是一个boost模板库,它需要一些额外的努力来寻找编译器错误。数字转换只是工作,但当然没有“免费午餐”;如果使用错误,你的结果就像内置数字一样容易搞乱。

要记住的事情:

  • 性能是精度的函数。保持控制!
  • 衡量您的精确度。例如,重复乘法可能会无限制地增加精度。消除数学中不必要的转换。
  • 许多函数(例如trig,log,exp,...)未实现有效性。你只能在需要放弃并接受受控错误(通过使用浮点类型)之前仔细斟酌这样的数学。
  • 您可以根据其精度要求分离您的程序。例如,当在2D中渲染时,转换为视图空间(-1..1),那么您可以将值截断为浮点并以良好的速度运行。
  • boost :: multiprecision有许多后端可以提高性能(虽然它们不会修复控制精度的错误)

我对boost mp类型使用以下定义。在我的情况下,我发现关闭表达模板更快。

namespace mp = boost::multiprecision;
typedef mp::number<mp::cpp_int_backend<>, mp::et_off>       int_mp;
typedef mp::number<mp::cpp_rational_backend, mp::et_off>    rational_mp;
typedef mp::number<mp::cpp_dec_float<0>, mp::et_off>        float_mp;  // 0 means 'unlimited'