当前位置: 首页 > 知识库问答 >
问题:

按不同顺序添加相同的双精度时的不同结果

孔理
2023-03-14

为什么在添加相同的数字时输出不同?

public class Test {

    public static void main(String a[]) {

        double[] x = new double[]{3.9, 4.3, 3.6, 1.3, 2.6};
        System.out.println(">>>>>>> " + sum(x));
    }

    public static double sum(double[] d) {

        double sum = 0;
        for (int i = 0; i < d.length; i++) {
            sum += d[i];
        }
        return sum;
    }
}

输出为:15.7

如果我交换值

double[] x = new double[] {2.6, 3.9, 4.3, 3.6, 1.3};

我得到的输出为:<代码>15.7000000000001

如何获得相同的输出?

共有3个答案

潘振国
2023-03-14

简单地将所有值相加,对于较长的数组,无论如何都会导致相对较大的错误(或者更准确地说:当总和已经是“大”时,错误将是“大”,并且应该添加更多的“小”数字)。

作为减少数值误差的一种可能性,您可以考虑http://en.wikipedia.org/wiki/Kahan_summation_algorithm:

public static double kahanSum(double d[])
{
    double sum = 0.0;
    double c = 0.0;
    for (int i=0; i<d.length; i++)
    {
        double y = d[i] - c;
        double t = sum + y;
        c = (t - sum) - y;
        sum = t;
    }
    return sum;        
}
楚博雅
2023-03-14

在一系列浮点算术运算中的每一步,系统都必须生成一个可以用浮点格式表示的结果。这可能会导致舍入错误,丢失一些信息。

当添加两个不同量级的数字时,较大的数字往往会控制必须丢弃哪些位。若您将一个大的数字和一个小的数字相加,由于结果的大小,小数字的许多位将由于舍入错误而丢失。当添加类似数量级的数字时,这种影响会减小。首先添加几个小数字,将大的震级数字保留到末尾,这样可以累积小数字的效果。

例如,考虑{1e17, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, -1e17}。没有任何四舍五入的确切答案将是147。按照上面显示的顺序相加得到112。“21.0”的每一个加法都必须四舍五入以适应一个数量级在1e17左右的数字。按照绝对数量级的升序相加得到144,更接近确切的答案。添加7个小数的部分结果正好是147,然后必须四舍五入以适应1e17左右的数字。

璩华辉
2023-03-14

浮点数在执行更多操作时会失去精度。通常,通过先将最小的数字相加,可以获得最高的精度。(因此,结果确实取决于操作顺序)

除了维护相同的操作顺序外,还必须使用strictfp在不同的平台上获得相同的结果。

或者更好的是,不要使用浮点:而是使用BigDecimal。

 类似资料:
  • 问题内容: 我使用maven程序集插件创建应用程序存档。包含在我pom中的所有依赖关系没有任何问题。 现在,我需要包括同一工件的两个或多个版本。 如果放在我的pom中 从源头上,Dependenvcy解析器删除了旧版本,并且存档中仅打包了1.1.0。 我尝试通过使用程序集xml描述符文件包括jar。而且我没有找到任何解决方案。 一种可能的解决方案是将所有需要的model.jar手动放入一个文件夹中

  • 我不明白为什么浮点值与双精度值不同。从下面的示例来看,对于相同的操作,float 提供的结果似乎与双精度型不同: 输出: 你能解释一下float和double之间的区别吗?

  • 问题内容: 想象一下一个Java类,它具有您可以在类中找到的大多数功能。例如:它从另一个类继承,实现了几个接口,包括一些“静态最终”常量,一些最终常量,一些静态变量,实例变量,一个静态块,一个未命名的代码块(仅是{}中的代码),构造函数,方法等 当所涉及的类首次加载到JVM中时,该类的各个部分以什么顺序初始化或加载到JVM中?JVM中的调用堆栈在加载时是什么样的?假设这里只有一个类加载器在工作。

  • 问题内容: 结构和具有相同的字段,但是如果以不同的顺序指定,它们将导致大小不同。为什么? 结构的大小为零。系统为多少内存分配? 谢谢。 问题答案: 1.结构尺寸 TL; DR; (摘要):如果对字段进行重新排序,将使用不同的隐式填充,并且隐式填充计入的大小。 注意结果取决于目标体系结构。 适用于您发布结果时,但是当,既大小的和将是24个字节。 结构的字段地址必须对齐,并且类型的字段地址必须为8字节

  • 以下是我目前的尝试: 我一直在思考如何动态地向列(mpg、cyl、disp)添加(1,2,3)。提前谢了。

  • 目前,我在主activity类和widget类中都声明了一个AsyncTask。除了中的结果处理之外,其他代码都是一样的(在activity中,检索到的结果转到activity中的textview,而在小部件中,它转到my widget中的textview)。 我想将移动到一个外部java文件中(以避免代码重复),并通过不同的结果处理方式从其他不同的类(如我的小部件和main activity)调