我的代码如下:
import java.util.Scanner;
public class MoVerkoopPrijs {
public static void main(String[] args) {
float inkoopPrijs;
final int BTW_HOOG = 21;
final int BTW_LAAG = 6;
double winstMarge;
Scanner in = new Scanner(System.in);
//hieronder wordt je inkoopprijs gevraagd en die moet je dan invoeren
System.out.println("wat is jouw inkoopprijs?");
inkoopPrijs = in.nextFloat();
//hieronder wordt je winstmarge gevraagd en die moet je dan ook invoeren
System.out.println("wat is jouw winstmarge?");
winstMarge = in.nextDouble();
//hieronder zie je de formules hoe je exlusief of inclusief BTW berekend
//hieronder zie je ook wat je moet doen als je de verkoopprijs wilt berekenen.
double winstGetal = (winstMarge / 100);
double verkoopPrijs = inkoopPrijs * (1 + winstGetal);
double inclusiefBtwLaag = (verkoopPrijs / 100) * BTW_LAAG + verkoopPrijs;
double inclusiefBtwHoog = (verkoopPrijs / 100) * BTW_HOOG + verkoopPrijs;
//hieronder print je dan de uiteindelijke prijzen uit
System.out.println("Verkoopprijs exclusief BTW:" + verkoopPrijs );
System.out.println("Verkoopprijs inclusief 6% BTW:" + inclusiefBtwLaag );
System.out.println("Verkoopprijs inclusief 21% BTW:" + inclusiefBtwHoog );
}
}
当前输出为:
Verkoopprijs exclusief BTW: 17.726400604248045
Verkoopprijs inclusief 6% BTW: 18.78998464050293
Verkoopprijs inclusief 21% BTW: 21.448944731140134
但是代码将输出中的最后两位小数弄乱了。 6%的实际输出应为:18.789984000000004
。我的代码有什么问题?
我尝试过从float转换为int并翻倍,但没有一个对我有用。
答案 0 :(得分:2)
计算机不是魔术。它们不能以无限的精度表示数字,因为这将需要不存在的无限内存。他们使用一种创新的解决方案来尝试以某种方式表示浮点数,从而涵盖您想表示的大多数数字,而这些数字仍然可以容纳32位(浮点数)或64位(双精度数)。但这确实是 inexact 。实际上,double / float只能表示有限数量的特定数字,如果您尝试使一个数字不是其中之一,那么您会得到它可以代表的最接近的数字。
那么,哪些数字可以和不能表示? 非常棘手,因为计算机以2为基数工作,而人类则倾向于以10为基数。
这带来了两个重要的教训:
每当您“渲染”双精度或浮点数(即向用户显示或将其显示为字符串)时,您必须指定给计算机正在寻找。 “仅打印”将不起作用,并且,如果尝试这样做(例如,使用System.out.println(someDouble);
,计算机只会猜测并且通常会猜错。这是正确的做法:System.out.printf("%.2f\n", someDouble)
,或者如果您不这样做, t要打印但要转换为字符串,String.format("%.2f", someDouble)
:您要告诉java打印/字符串化它,以便在逗号后最多得到2位数字。如果2.7表示为2.6999999999999999852,则仍会打印2.7,因为这是距离2.6999999999999999852最接近的2位逗号后字符串表示形式。
如果您想保证精度(通常在赚钱时是个好主意!),请勿完全使用double或float 。通常用钱解决的方法是使用int
或long
并存储美分而不是欧元或美元。有人会建议您改用BigDecimal
,但我建议您不要这样做,除非您真的知道自己需要它。划分资金是很棘手的,并且需要一种自定义策略,即使BigDecimal
也不能将4美分分配给3个银行帐户,而不能四舍五入或崩溃。如果您需要乘以详细信息,BigDecimal
是一个更合理的想法,这会带来很多外汇。在您的情况下,需要应用增值税计算时,请不要理会并坚持使用以整数或多位存储的美分。
使用float
而不是double
时会得到不同结果的原因是,浮点数仅占用32位内存,因此float
可以精确表示的数字更少,与double
相对。 Java的System.out.println将应用四舍五入(但不多)。四舍五入往往不足以掩盖float
的不准确性。
18.78998464050293
是最能准确代表18.789984000000004
实际答案的数字。