Java Double 值 = 0.01 更改为 0.009999999999999787

发布于 2024-12-04 13:26:49 字数 1485 浏览 2 评论 0原文

可能的重复:
为什么不使用 Double 或 Float 来表示货币?

我正在为我的高中课程编写一个基本的 Java 命令行程序。我们现在只处理变量。它用于计算购买后找零中任何类型的纸币和硬币的数量。这是我的程序:

class Assign2c {
    public static void main(String[] args) {
        double cost = 10.990;
        int paid = 20;
        double change = paid - cost;
        int five, toonie, loonies, quarter, dime, nickel, penny;

        five = (int)(change / 5.0);
        change -= five * 5.0;

        toonie = (int)(change / 2.0);
        change -= toonie * 2.0;

        loonies = (int)change;
        change -= loonies;

        quarter = (int)(change / 0.25);
        change -= quarter * 0.25;

        dime = (int)(change / 0.1);
        change -= dime * 0.1;

        nickel = (int)(change / 0.05);
        change -= nickel * 0.05;

        penny = (int)(change * 100);
        change -= penny * 0.01;

        System.out.println("$5   :" + five);
        System.out.println("$2   :" + toonie);
        System.out.println("$1   :" + loonies);
        System.out.println("$0.25:" + quarter);
        System.out.println("$0.10:" + dime);
        System.out.println("$0.05:" + nickel);
        System.out.println("$0.01:" + penny);
    }
}

它应该一切正常,但在最后一步,当还有 0.01 美元剩余时,便士数量应该是 1,但实际上是 0。在单步执行代码并将更改值输出到控制台几分钟后,我发现在最后一步当change = 0.01时,它变成了0.009999999999999787。为什么会发生这种情况?

Possible Duplicate:
Why not use Double or Float to represent currency?

I'm writing a basic command-line program in Java for my high school course. We're only working with variables right now. It's used to calculate the amount of bills and coins of whatever type in your change after a purchase. This is my program:

class Assign2c {
    public static void main(String[] args) {
        double cost = 10.990;
        int paid = 20;
        double change = paid - cost;
        int five, toonie, loonies, quarter, dime, nickel, penny;

        five = (int)(change / 5.0);
        change -= five * 5.0;

        toonie = (int)(change / 2.0);
        change -= toonie * 2.0;

        loonies = (int)change;
        change -= loonies;

        quarter = (int)(change / 0.25);
        change -= quarter * 0.25;

        dime = (int)(change / 0.1);
        change -= dime * 0.1;

        nickel = (int)(change / 0.05);
        change -= nickel * 0.05;

        penny = (int)(change * 100);
        change -= penny * 0.01;

        System.out.println("$5   :" + five);
        System.out.println("$2   :" + toonie);
        System.out.println("$1   :" + loonies);
        System.out.println("$0.25:" + quarter);
        System.out.println("$0.10:" + dime);
        System.out.println("$0.05:" + nickel);
        System.out.println("$0.01:" + penny);
    }
}

It should all work but at the last step when there's $0.01 leftover, number of pennies should be 1 but instead, it's 0. After a few minutes of stepping into the code and outputting the change value to the console, I've found out that at the last step when change = 0.01, it changes to 0.009999999999999787. Why is this happening?

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

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

发布评论

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

评论(8

无尽的现实 2024-12-11 13:26:49

使用 double 作为货币是一个坏主意,为什么不使用 Double 或 Float 来表示货币?。我建议使用 BigDecimal 或以美分进行每次计算。

Using double for currency is a bad idea, Why not use Double or Float to represent currency?. I recommend using BigDecimal or doing every calculation in cents.

故事↓在人 2024-12-11 13:26:49

0.01 没有精确的浮点表示(就此而言,0.1 和 0.2 也没有)。

您可能应该使用代表便士数量的整数类型进行所有数学计算。

0.01 does not have an exact representation in floating-point (and neither do 0.1 nor 0.2, for that matter).

You should probably do all your maths with integer types, representing the number of pennies.

铜锣湾横着走 2024-12-11 13:26:49

double 在内部不是以十进制保存的,而是以二进制保存的。它们的存储格式相当于“100101乘以10000”(我正在简化,但这是基本思想)。不幸的是,这些二进制值的组合没有精确到十进制 0.01,这就是其他答案所说的浮点数不是 100% 准确,或者 0.01 在浮点数中没有精确表示时的意思。观点。

处理这个问题有多种方法,有些方法比其他方法更复杂。针对您的情况,最好的解决方案可能是在各处使用 int 并将值保留为美分。

doubles aren't kept in decimal internally, but in binary. Their storage format is equivalent to something like "100101 multiplied by 10000" (I'm simplifying, but that's the basic idea). Unfortunately, there's no combination of these binary values that works out to exactly decimal 0.01, which is what the other answers mean when they say that floating point numbers aren't 100% accurate, or that 0.01 doesn't have an exact representation in floating point.

There are various ways of dealing with this problem, some more complicated than others. The best solution in your case is probably to use ints everywhere and keep the values in cents.

缱倦旧时光 2024-12-11 13:26:49

正如其他人已经说过的,不要使用双打进行财务计算。

本文http://download.oracle.com/docs /cd/E19957-01/806-3568/ncg_goldberg.html(每个计算机科学家应该了解的浮点知识算术)是理解计算机中浮点数学的必读书籍。

As the others already said, do not use doubles for financial calculations.

This paper http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html (What Every Computer Scientist Should Know About Floating-Point Arithmetic) is a must-read to understand floating point math in computers.

糖粟与秋泊 2024-12-11 13:26:49

浮点数永远不会 100% 准确(不完全正确,请参阅下面的评论)。你永远不应该直接比较它们。还有整数舍入。最好的方法可能是先以美分计算,然后再转换为美元(1 美元 == 100 美分)。通过转换为整数,您会失去精度。

Floating point numbers are never 100% accurate (not quite true, see comments below). You should never compare them directly. Also integer rounding. The best way to do this would probably be to do it in cents and convert to dollars later (1 dollar == 100 cents). By converting to an integer you are losing precision.

为你鎻心 2024-12-11 13:26:49

它是一个 float(double)

你不应该用它来计算金钱......

我建议使用 int 值并对便士进行操作

its a float(double)

You should not use it to compute money....

I recommend using int values and operate on pennys

末骤雨初歇 2024-12-11 13:26:49

这是一个已经多次出现的问题。最重要的是,在使用二进制浮点数(Java 需要)的计算机上,只有分母是 2 的幂的分数才能精确表示。

同样的问题也出现在十进制中。例如,1/3 会变成 0.3333333...,因为 3 不是 10 的因数(我们使用的十进制基数)。同样是 1/17、1/19 等。

在二进制浮点数中,也会出现相同的基本问题。主要区别在于,在十进制中,由于 5 是 10 的因数,因此可以精确表示 1/5(1/5 的倍数也可以)。由于 5 不是 2 的因数,因此 1/5 无法用二进制浮点数精确表示。

然而,与普遍的看法相反,有些分数可以精确地表示——特别是那些分母仅以2为质因数的分数(例如,1/8或1/256可以精确地表示)。

This is a problem that's arisen many times over. The bottom line is that on a computer that uses binary floating point (which Java requires), only fractions in which the denominator is a power of 2 can be represented precisely.

The same problem arises in decimal. 1/3, for example, turns into 0.3333333..., because 3 isn't a factor of 10 (the base we're using in decimal). Likewise 1/17, 1/19, etc.

In binary floating point, the same basic problem arises. The main difference is that in decimal, since 5 is a factor of 10, 1/5 can be represented precisely (and so can multiples of 1/5). Since 5 is not a factor of 2, 1/5 cannot be represented precisely in binary floating point.

Contrary to popular belief, however, some fractions can be represented precisely -- specifically those fractions whose denominators with only 2 as a prime factor (e.g., 1/8 or 1/256 can be represented precisely).

吹梦到西洲 2024-12-11 13:26:49

我确信您知道某些分数的小数表示形式会终止(例如 .01),而有些则不会(例如 2/3=.66666...)。问题是,哪些分数终止会根据你所处的基础而变化。特别是,.01 不以二进制结尾,因此即使 double 提供了很多精度,它也无法准确表示 .01。正如其他人所说,使用 BigDecimal 或定点整数计算(将所有内容转换为美分)可能最适合货币;要了解有关浮点的更多信息,您可以从浮点指南 - 每个程序员应该了解浮点知识开始算术

I'm sure you know that some fractions' decimal representations terminate (e.g. .01) while some don't (e.g. 2/3=.66666...). The thing is that which fractions terminate changes depending on what base you're in; in particular, .01 doesn't terminate in binary, so even though double provides a lot of precision it can't represent .01 exactly. As others said, using BigDecimal or fixed-point integer computations (converting everything to cents) is probably best for currency; to learn more about floating point, you could start at The Floating-Point Guide- What Every Programmer Should Know About Floating-Point Arithmetic.

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