我在“Ask Ubuntu”论坛上询问了以下问题,并被告知该问题不适合该论坛。有人建议我在这里问我的问题。如果这不是这个问题的适当场所,我会提前道歉。
我目前使用java作为我的默认语言。此外,我目前正在运行Kubuntu版本12.04。我正在将一个c ++程序转换为java,而java程序的结果与c ++程序的结果不匹配。当我意识到java程序产生了正确的结果并且c ++程序没有产生正确的结果时,我开始四处寻找问题。我的问题是,任何人都可以解释为什么c ++会产生错误的结果并且可以修复吗?
我写了两个最小程序来说明问题。我还写了一个脚本文件来显示这两个程序,编译并运行它们。结果如下。显然,有效数字位于相同的邻域中,但是当处理诸如30次幂的10的大功率时,差异是显着的。以下是我的测试程序和脚本的结果:
Linux Pegasus 3.2.0-54-generic#82-Ubuntu SMP Tue Sep 10 20:08:42 UTC 2013 x86_64 x86_64 x86_64 GNU / Linux
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double testValue;
//---------------------------------------------------------------------
testValue = 1.0e0 * 1.9891e30;
cout << scientific << showpoint << right << setprecision(20)
<< "The test value = "
<< setw(25) << testValue
<< " the test value should be 1.9891e30\n"
<< endl;
return 0;
}
class test
{
public static void main (String[] args)
{
double testValue;
//---------------------------------------------------------------------
testValue = 1.0e0 * 1.9891e30;
System.out.format
(
"The test value = %.20e the test value should be 1.9891e30%n", testValue
);
} // end main
}
测试值= 1.98909999999999988781e + 30测试值应为1.9891e30
测试值= 1.98910000000000000000e + 30测试值应为1.9891e30
显然,c ++程序生成的testValue的值是错误的,而java程序生成的testValue的值是正确的。任何和所有洞察这个问题将不胜感激。我搜索谷歌和这里使用搜索词“c ++错误计算”没有任何重要发现。
答案 0 :(得分:0)
我不确定你觉得这个计算是错误的?浮点数学受到值的微小差异的影响。在具有单个编译器的单个机器上,浮点值是确定性的,但是,对于不同的语言和不同的编译器,您不能保证具有相同的结果。
我的老教授布鲁斯道森给出了一个很好的概述: http://randomascii.wordpress.com/2012/04/05/floating-point-complexities/ http://randomascii.wordpress.com/2013/07/16/floating-point-determinism/
您在上面看到的结果对我来说很合适。也许您应该在小数点后舍入到3位数并使用它来比较结果值。对于浮点,您将很难在不同语言和编译器之间更准确地使用它。
此外,我建议下次使用“浮点不准确”作为更好的Google搜索。
答案 1 :(得分:0)
当Java代码对值进行四舍五入时,C ++代码将打印出实际值。请注意,0.0001
与0.1
一样,无法用二进制表示。
您可以使用BigDecimal
来打印实际值,这与您的C ++输出相同:
import java.math.*;
class test
{
public static void main (String[] args)
{
double testValue;
testValue = 1.0e0 * 1.9891e30;
BigDecimal realvalue = new BigDecimal(testValue);
System.out.format
(
"The test value = %.20e the test value should be 1.9891e30%n", realvalue
);
}
}
<强>输出强>
测试值= 1.98909999999999988781e + 30应为测试值 1.9891e30
AFAIK,C ++和Java中的double
都将保持相同的值,但是当打印出来时,你会看到差异。