如何从 cpp_dec_float_50 转换为 cpp_int?一般关于浮点数?

Posted

技术标签:

【中文标题】如何从 cpp_dec_float_50 转换为 cpp_int?一般关于浮点数?【英文标题】:How to convert from cpp_dec_float_50 to cpp_int? And regarding floating points in general? 【发布时间】:2013-04-16 09:38:19 【问题描述】:

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

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 来存储分子和分母,因为分子和分母可能会变得很大。它工作正常。但问题是我正在制作的程序需要很多时间。我认为这是因为必须处理巨大的整数。

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

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

谢谢。很抱歉,如果其中任何一个问题被认为是非常愚蠢或愚蠢的问题。 我还在学习。

【问题讨论】:

一个must read. 您的库不提供cpp_float_dec_50cpp_int 之间的转换例程吗?如果没有,我会感到非常惊讶。 感谢您的链接。我会通过它。 :) 不,我找不到转换的方式。事实上,这个页面说这种有损转换是不允许的。 boost.org/doc/libs/1_53_0/libs/multiprecision/doc/html/… @AlexeyFrunze:链接到 Goldberg 论文既简单又时尚,但通常信息量不足且不恰当。在这种情况下,直到大文件的一半,它才开始讨论与这个问题相关的任何事情,语言中的歧义允许明显相同的数学表达式进行不同的评估。并且论文只是笼统地讨论它,并没有解释适用于这种情况的特定语言规则和行为。 【参考方案1】:

您需要决定是否需要精确的表示。如果 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'

【讨论】:

很好的答案! et_off 到底做了什么?提前非常感谢您! 'mp::et_off' 在这种情况下意味着'关闭此数据类型的表达式模板'。表达式模板存储表达式列表以供以后计算,而不是立即计算表达式。有记账成本,但在某些情况下可能更有效。文档:boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/…

以上是关于如何从 cpp_dec_float_50 转换为 cpp_int?一般关于浮点数?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数组从两个不同的表列转换为平行行?

如何将字节从 uint64_t 转换为 double?

如何将文件的AIX时间戳转换为EPOCH

如何从 __callStatic() 方法中提取 $parameters 数组,以便使用 __ToString() 方法进一步转换为字符串?

如何将 cv::Mat 类型从 CV_16UC1 转换为 CV_8UC1

如何将对象转换为字典?