c++ - 在 C++ 中处理极其精确的浮点计算时保持准确性的标准方法是什么?

标签 c++ math precision gmp

我正在将程序从 Scilab 转换为 C++ (类似于 Matlab)并且我需要保持与之前的代码相同的精度水平。

注意:尽管保持相同的精度水平是理想的。如果最终结果存在某些错误,这是可以接受的。我面临的问题(如下所示)是由于循环造成的,因此计算错误会很快复合。但如果最终结果只有千分之一左右(例如 1/1000 与 1/1001),那就不会有问题。

我简要研究了许多不同的方法来做到这一点,包括:

Int 与 Float 示例:不要使用浮点 12.45,而是将其存储为整数 124,500。然后在适当的时候将所有内容转换回来即可。注意:我不太确定这将如何与我正在使用的代码一起工作(下面有更多详细信息)。

我的程序如何产生错误结果的示例:

for (int i = 0; i <= 1000; i++)
{
    for (int j = 0; j <= 10000; j++)
    {
        // This calculation will be computed with less precision than in Scilab
        float1 = (1.0 / 100000.0);

        // The above error of float2 will become significant by the end of the loop
        float2 = (float1 + float2);
    }
}

我的问题是:

是否有一种普遍接受的方法来保持浮点运算的准确性,或者上述方法之一就足够了?

最佳答案

在移植这样的代码时保持精度是非常困难的。并不是因为这些语言对浮点是什么有隐含的不同观点,而是因为不同的算法或精度限制的假设是什么。例如,在Scilab中进行数值积分时,可以使用高斯求积法。而您可以尝试使用梯形方法。两者可能都处理相同的 IEEE754 单精度 float ,但由于两种算法的收敛特性,您会得到不同的答案。那么如何解决这个问题呢?

嗯,您可以浏览 Scilab 源代码并查看它针对您需要的每项内容使用的所有算法。然后,您可以复制这些算法,处理 Scilab 隐式执行的任何数据预处理或后处理(如果有)。这是很多工作。而且,坦率地说,这可能不是打发时间的最佳方式。相反,我会考虑使用 developer's documentation 中的与其他语言的接口(interface)部分。了解如何直接从 C、C++、Java 或 Fortran 代码调用 Scilab 函数。

当然,使用第二个选项时,您必须考虑如何分发代码(如果需要)。Scilab 具有 GPL 兼容许可证,因此您可以将其与代码捆绑在一起。然而,它相当大(~180MB),您可能只想捆绑您需要的部分(例如,您不需要整个解释器系统)。这是以不同方式进行的更多工作,但保证与您当前的 Scilab 解决方案的数值兼容性。

关于c++ - 在 C++ 中处理极其精确的浮点计算时保持准确性的标准方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37667386/

相关文章:

javascript - 如何直接从原生 JavaScript 前端与 Emscripten Web Worker 交互

c++ - 为什么我的程序不近似 pi?

java - 开关、if-else 和数学

c - 获取 float 的指数

c++ - 如何专门化容器和枚举的模板

c++ - 为什么类构造函数为其成员生成析构函数?

python - Project Euler #4 算法的可能优化

c++ - 为什么这两个代码片段会产生不同的结果? ( float , double )

c++ - printf 如何在小数点后打印 53 位?

c++ - 空流,我必须包括 ostream 吗?