我正在为我的高中课程编写一个基本的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.在进入代码并输出更改值到控制台几分钟后,我已经发现在变量= 0.01的最后一步,它变为0.009999999999999787。为什么会这样?
答案 0 :(得分:8)
将double
用于货币是一个坏主意,Why not use Double or Float to represent currency?。我建议使用BigDecimal
或以分为单位进行每次计算。
答案 1 :(得分:7)
0.01在浮点中没有精确的表示(对于这个问题,也没有0.1和0.2)。
你应该用整数类型做所有的数学运算,代表便士的数量。
答案 2 :(得分:4)
doubles
内部不保留十进制,而是二进制。他们的存储格式相当于“100101
乘以10000
”(我正在简化,但这是基本的想法)。不幸的是,没有这些二进制值的组合精确到小数0.01,这是其他答案的意思,当他们说浮点数不是100%准确,或0.01没有精确的浮动表示点。
有多种方法可以解决这个问题,有些方法比其他方法更复杂。在您的情况下,最好的解决方案可能是在任何地方使用int
并将值保持为美分。
答案 3 :(得分:1)
浮点数永远不会100%准确(不完全正确,请参阅下面的评论)。你永远不应该直接比较它们。也是整数舍入。做到这一点的最好方法可能是以美分计算,然后转换成美元(1美元= 100美分)。通过转换为整数,您将失去精确度。
答案 4 :(得分:1)
正如其他人已经说过的那样,不要使用双打进行财务计算。
本文http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html(每个计算机科学家应该知道的关于浮点算术的内容)是理解计算机中浮点数学的必读内容。
答案 5 :(得分:0)
它的浮动(双)
你不应该用它来计算金钱......
我建议使用int值并在pennys上运行
答案 6 :(得分:0)
这是一个多次出现的问题。底线是在使用二进制浮点(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)可以表示的分数精确地)。
答案 7 :(得分:0)
我确定你知道某些分数的十进制表示终止(例如.01)而有些则没有(例如2/3 = .66666 ......)。问题在于,根据您所处的基础,哪些分数会终止变化;特别是,.01不以二进制结束,因此即使double提供了很多精度,它也不能完全代表.01。正如其他人所说,使用BigDecimal或定点整数计算(将所有内容转换为美分)可能最适合货币;要了解有关浮点的更多信息,您可以从The Floating-Point Guide- What Every Programmer Should Know About Floating-Point Arithmetic开始。