在 C++ 中处理极其精确的浮点计算时,保持准确性的标准方法是什么?
What is the standard way to maintain accuracy when dealing with incredibly precise floating point calculations in C++?
我正在将程序从 Scilab(类似于 Matlab)转换为 C++,我需要保持与之前代码相同的精度水平。
注意:虽然保持相同的精度水平是最理想的。如果完成的结果有一些错误是可以接受的。我面临的问题(正如我将在下面展示的那样)是由于循环造成的,因此计算错误很快就会增加。但是如果最后的结果只差千分之一左右(比如1/1000 vs 1/1001)就没有问题了
我已经简要研究了多种不同的方法,包括:
- GMP(多精度
算术库)
- Using integers instead of floats (see example below)
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);
}
}
我的问题是:
是否有一种普遍接受的方法来保持浮点运算的准确性,或者上述方法之一是否足够?
如果您的编译器支持,请使用 BCD(二进制编码的十进制)
山姆
好吧,如果您使用 GCC 编译器,另一种选择是使用 quadmath/__float128 类型。
Is there a generally accepted way to go about retaining accuracy in floating
point arithmetic
"Generally accepted"太宽泛了,所以没有。
will one of the above methods suffice?
是的。特别是 gmp 似乎是一个标准的选择。我也会看看 Boost Multiprecision library.
手工编码的整数方法也可以工作,但肯定不是选择的方法:它需要更多的编码,更严格的存储和处理任意精确整数的方法。
像这样移植代码时很难保持精度。不是因为语言对 float
是什么有不同的看法,而是因为不同的算法或准确度限制的假设是什么。例如,在Scilab中进行数值积分时,可能会用到高斯求积法。而您可以尝试使用梯形方法。两者可能都在处理相同的 IEEE754 单精度浮点数,但由于两种算法的收敛特性,您会得到不同的答案。那么你如何解决这个问题?
好吧,您可以浏览 Scilab 源代码并查看它为您需要的每件事使用的所有算法。然后,您可以复制这些算法,处理 Scilab 隐式执行的数据的任何预处理或 post 处理(如果有的话)。这是很多工作。而且,坦率地说,这可能不是消磨时间的最佳方式。相反,我会研究使用 developer's documentation 中的 Interfacing with Other Languages 部分,了解如何直接从 C、C++、Java,或 Fortran 代码。
当然,对于第二个选项,您必须考虑如何分发您的代码(如果需要的话)。Scilab 具有与 GPL 兼容的许可证,因此您可以将其与您的代码捆绑在一起。然而,它相当大(~180MB),你可能只想捆绑你需要的部分(例如,你不需要整个解释器系统)。这是以不同的方式进行的更多工作,但保证与您当前的 Scilab 解决方案在数值上兼容。
我正在将程序从 Scilab(类似于 Matlab)转换为 C++,我需要保持与之前代码相同的精度水平。
注意:虽然保持相同的精度水平是最理想的。如果完成的结果有一些错误是可以接受的。我面临的问题(正如我将在下面展示的那样)是由于循环造成的,因此计算错误很快就会增加。但是如果最后的结果只差千分之一左右(比如1/1000 vs 1/1001)就没有问题了
我已经简要研究了多种不同的方法,包括:
- GMP(多精度 算术库)
- Using integers instead of floats (see example below)
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);
}
}
我的问题是:
是否有一种普遍接受的方法来保持浮点运算的准确性,或者上述方法之一是否足够?
如果您的编译器支持,请使用 BCD(二进制编码的十进制)
山姆
好吧,如果您使用 GCC 编译器,另一种选择是使用 quadmath/__float128 类型。
Is there a generally accepted way to go about retaining accuracy in floating point arithmetic
"Generally accepted"太宽泛了,所以没有。
will one of the above methods suffice?
是的。特别是 gmp 似乎是一个标准的选择。我也会看看 Boost Multiprecision library.
手工编码的整数方法也可以工作,但肯定不是选择的方法:它需要更多的编码,更严格的存储和处理任意精确整数的方法。
像这样移植代码时很难保持精度。不是因为语言对 float
是什么有不同的看法,而是因为不同的算法或准确度限制的假设是什么。例如,在Scilab中进行数值积分时,可能会用到高斯求积法。而您可以尝试使用梯形方法。两者可能都在处理相同的 IEEE754 单精度浮点数,但由于两种算法的收敛特性,您会得到不同的答案。那么你如何解决这个问题?
好吧,您可以浏览 Scilab 源代码并查看它为您需要的每件事使用的所有算法。然后,您可以复制这些算法,处理 Scilab 隐式执行的数据的任何预处理或 post 处理(如果有的话)。这是很多工作。而且,坦率地说,这可能不是消磨时间的最佳方式。相反,我会研究使用 developer's documentation 中的 Interfacing with Other Languages 部分,了解如何直接从 C、C++、Java,或 Fortran 代码。
当然,对于第二个选项,您必须考虑如何分发您的代码(如果需要的话)。Scilab 具有与 GPL 兼容的许可证,因此您可以将其与您的代码捆绑在一起。然而,它相当大(~180MB),你可能只想捆绑你需要的部分(例如,你不需要整个解释器系统)。这是以不同的方式进行的更多工作,但保证与您当前的 Scilab 解决方案在数值上兼容。