【问题标题】:Java: Inaccuracy using double [duplicate]Java:使用双精度[重复]
【发布时间】:2011-10-21 22:55:32
【问题描述】:

可能重复:
Retain precision with Doubles in java
Strange floating-point behaviour in a Java program

我正在制作一个直方图类,但遇到了一个奇怪的问题。

这是该类的基础知识,还有更多方法,但它们与问题无关。

private int[] counters;
private int numCounters;
private double min, max, width;

public Histogram(double botRange, double topRange, int numCounters) {
    counters = new int[numCounters];
    this.numCounters = numCounters;
    min = botRange;
    max = topRange;
    width = (max - min) / (double) numCounters;
}

public void plotFrequency() {
    for (int i = 0; i < counters.length; i++) {
        writeLimit(i * width, (i + 1) * width);
        System.out.println(counters[i]);
    }
}

private void writeLimit(double start, double end) {
    System.out.print(start + " <= x < " + end + "\t\t");
}

当我绘制频率时会出现问题。我创建了 2 个实例。 新直方图(0, 1, 10); 新直方图(0, 10, 10);

这是他们输出的内容。

Frequecy
0.0 <= x < 0.1      989
0.1 <= x < 0.2      1008
0.2 <= x < 0.30000000000000004      1007
0.30000000000000004 <= x < 0.4      1044
0.4 <= x < 0.5      981
0.5 <= x < 0.6000000000000001       997
0.6000000000000001 <= x < 0.7000000000000001        1005
0.7000000000000001 <= x < 0.8       988
0.8 <= x < 0.9      1003
0.9 <= x < 1.0      978

Frequecy
0.0 <= x < 1.0      990
1.0 <= x < 2.0      967
2.0 <= x < 3.0      1076
3.0 <= x < 4.0      1048
4.0 <= x < 5.0      971
5.0 <= x < 6.0      973
6.0 <= x < 7.0      1002
7.0 <= x < 8.0      988
8.0 <= x < 9.0      1003
9.0 <= x < 10.0     982    

所以我的问题是,为什么我在第一个示例中得到了非常长的小数限制,而在第二个示例中没有?

【问题讨论】:

标签: java floating-point double


【解决方案1】:

双打并不准确。

这是因为有可能的实数和只有有限的位数来表示这些数字。

看看:what every programmer should know about floating point arithmetic

【讨论】:

    【解决方案2】:

    来自The Floating-Point Guide

    因为在内部,计算机使用一种格式(二进制浮点) 根本无法准确表示像 0.1、0.2 或 0.3 这样的数字

    当代码被编译或解释时,你的“0.1”已经 以该格式四舍五入到最接近的数字,这会导致小 甚至在计算发生之前就有舍入误差。

    这就是您的第一个示例。第二种只涉及整数,不涉及分数,整数可以用二进制浮点格式(最多52位)精确表示。

    【讨论】:

      【解决方案3】:

      有些小数不能用双精度值精确表示。 0.3 是这些值之一。

      所有小于某个数字(我忘记了)的整数值恰好有一个双精度值的精确表示,所以你看不到近似值。

      考虑我们如何看待数字:数字 123 表示为 (1 * 100) + (2 * 10) + (3 * 1)。我们使用 10 作为我们的基础。二进制数使用两个。因此,当您查看数字的分数时,如何通过添加 2 的单个幂来表示 0.3?你不能。你能想到的最好的大约是 0.30000000000000004(我必须看到确切的二进制数字才能看到它是如何达到的)。

      【讨论】:

      • 所以我应该把它剪掉一定数量的数字以获得更友好的价值吗?
      【解决方案4】:

      在第二种情况下,它们正在四舍五入。另请参阅 Ruby - Multiplication issue — 这是同样的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-06
        • 2015-04-25
        • 2013-01-28
        • 1970-01-01
        • 2012-07-23
        • 1970-01-01
        • 2019-11-07
        相关资源
        最近更新 更多