1

我在“Ask Ubuntu”论坛上问了以下问题,并被告知该问题不适合该论坛。有人建议我在这里问我的问题。如果这不是这个问题的合适地点,我提前道歉。

我目前使用 java 作为我的默认语言。另外,我目前正在运行 Kubuntu 12.04 版。我正在将 c++ 程序转换为 java,而 java 程序的结果与 c++ 程序的结果不匹配。当我意识到 java 程序产生了正确的结果而 c++ 程序没有产生正确的结果时,我开始四处寻找问题。我的问题是任何人都可以解释为什么 c++ 会产生错误的结果并且可以修复吗?

我写了两个最小的程序来说明这个问题。我还编写了一个脚本文件来显示这两个程序,编译并运行它们。结果如下。很明显,有效数字在同一个邻域中,但是在处理 10 的大幂(例如 30 次幂)时,差异是显着的。以下是我的测试程序和脚本的结果:

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

c++源代码

#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;
}

java源码

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
}

g++ 测试

测试值 = 1.98909999999999988781e+30 测试值应该是 1.9891e30

java测试

测试值 = 1.98910000000000000000e+30 测试值应该是 1.9891e30

显然 c++ 程序产生的 testValue 的值是错误的,而 java 程序产生的 testValue 的值是正确的。对此问题的任何和所有见解将不胜感激。我已经使用搜索词“c++ 错误计算”搜索了谷歌和这里,但没有任何重要发现。

4

2 回答 2

0

我不确定你觉得这个计算是错误的吗?浮点数学会受到值的微小差异的影响。在具有单个编译器的单台机器上,浮点值是确定性的,但是,对于不同的语言和不同的编译器,不能保证得到相同的结果。

我的老教授 Bruce Dawson 给出了一个很好的概述: http ://randomascii.wordpress.com/2012/04/05/floating-point-complexities/ http://randomascii.wordpress.com/2013/07/16/floating-点确定性/

你在上面看到的结果对我来说看起来很好。也许您应该在小数点后四舍五入到 3 位,并使用它来比较您的结果值。使用浮点,您将很难在不同的语言和编译器之间获得更准确的结果。

另外,我建议下次使用“浮点不准确”作为更好的 Google 搜索。

于 2013-10-15T04:10:15.553 回答
0

C++ 代码打印出实际值,而 Java 代码对值进行四舍五入。请记住,数字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,double在 C++ 和 Java 中,两者都具有相同的值,但是在将它们打印出来时,您会看到不同之处。

于 2013-10-15T04:35:25.633 回答