我正在从Scilab(类似于Matlab)将程序转换为C ++,我需要保持前一代码保持的相同精度级别。
注意:虽然保持相同的精度水平是理想的。如果完成的结果有某些错误,则可以接受。我面临的问题(如下所示)是由于循环,因此计算错误很快就会复杂化。但如果最终结果只有千分之一左右(例如1/1000 vs 1/1001),它就不会成为问题。
我简要介绍了一些不同的方法,包括:
Int vs Float示例: 而不是使用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);
}
}
我的问题是:
是否有一种普遍接受的方法可以保留浮点运算的准确性,或者上述方法之一是否足够?
答案 0 :(得分:3)
在移植此类代码时保持精确度非常困难。不是因为这些语言对float
的含义有着截然不同的观点,而是因为准确度限制的不同算法或假设是什么。例如,当在Scilab中执行数值积分时,它可以使用高斯求积法。而您可能尝试使用梯形方法。这两者可能都在使用相同的IEEE754单精度浮点数,但由于两种算法的收敛特性,您将获得不同的答案。那你怎么解决这个问题呢?
好吧,您可以浏览Scilab源代码,查看它所使用的所有算法。然后,您可以复制这些算法,处理Scilab隐含执行的任何数据的预处理或后处理(如果有的话)。这需要做很多工作。而且,坦率地说,可能不是花时间的最佳方式。相反,我将研究如何使用developer's documentation中的与其他语言的接口部分来了解如何直接从C,C ++,Java或Fortran代码调用Scilab函数。< / p>
当然,使用第二个选项,您必须考虑如何分发代码(如果需要).Scilab具有GPL兼容许可证,因此您可以将其与代码捆绑在一起。但是,它很大(约180MB),你可能只想捆绑你需要的部分(例如,你不需要整个翻译系统)。这是更多的工作方式,但保证与您当前的Scilab解决方案的数字兼容性。
答案 1 :(得分:1)
是否有一种普遍接受的方法可以保持漂浮的准确性 点算术
“普遍接受”太宽泛,所以没有。
上述方法之一是否足够?
是。特别是gmp似乎是一个标准的选择。我还要看看Boost Multiprecision library。
手动编码的整数方法也可以起作用,但肯定不是选择的方法:它需要更多的编码,更严格的方法来存储和处理非常精确的整数。
答案 2 :(得分:0)
如果您的编译器支持它,请使用BCD(二进制编码的十进制)
萨姆
答案 3 :(得分:0)
嗯,如果使用GCC编译器,另一种选择是使用quadmath / __ float128类型。