Java:使用 double 不准确

发布于 2024-12-11 13:26:37 字数 1911 浏览 0 评论 0原文

可能的重复:
在java中使用双精度保持精度
Java 程序中奇怪的浮点行为

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

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

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    

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

Possible Duplicate:
Retain precision with Doubles in java
Strange floating-point behaviour in a Java program

I'm making a histogram class, and I'm encountering a weird issue.

Here are the basics of the class, there are more methods but they aren't relevant to the issue.

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");
}

the problem happens when I plot the frequencies. I've created 2 instances.
new Histogram(0, 1, 10);
new Histogram(0, 10, 10);

This is what they output.

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    

So my question is, why am I getting the really long decimal limits in the first example, but not the second one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

弥繁 2024-12-18 13:26:37

双打并不准确。

这是因为存在无限可能的实数,而表示这些数字的位数却是有限的

看一下:每个程序员都应该了解浮点知识算术

doubles are not exact.

It is because there are infinite possible real numbers and only finite number of bits to represent these numbers.

have a look at: what every programmer should know about floating point arithmetic

云朵有点甜 2024-12-18 13:26:37

来自浮点指南

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

当代码被编译或解释时,你的“0.1”已经是
四舍五入到该格式中最接近的数字,这会导致一个小的
即使在计算发生之前也会出现舍入误差。

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

From The Floating-Point Guide:

Because internally, computers use a format (binary floating-point)
that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.

When the code is compiled or interpreted, your “0.1” is already
rounded to the nearest number in that format, which results in a small
rounding error even before the calculation happens.

That accounts for your first example. The second one only involves integers, not fractions, and integers can be represented exactly in the binary floating-point format (up to 52 bits).

静待花开 2024-12-18 13:26:37

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

所有小于某个数字(我忘记了哪个数字)的整数值碰巧都有一个双精度值的精确表示,因此您看不到近似值。

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

Some decimals cannot be exactly represented by double values. 0.3 is one of those values.

All integer values less than a certain number (I forget which) happen to have an exact representation by a double value, so you don't see the approximation.

Consider how we think of numbers: the number 123 is represented as (1 * 100) + (2 * 10) + (3 * 1). We use 10 as our base. Binary numbers use two. So when you look at fractions of a number, how could you represent 0.3 by adding individual powers of 2? You can't. The best you can come up with is about 0.30000000000000004 (I'd have to see the exact binary digits to see how it reaches that).

成熟稳重的好男人 2024-12-18 13:26:37

他们在第二种情况下四舍五入。另请参阅Ruby - 乘法问题 - 这是同样的问题。

They're getting rounded in the second case. See also Ruby - Multiplication issue — it's the same problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文