Java 我的代码没有按预期工作。十进制输出不是它应该的样子

Java 我的代码没有按预期工作。十进制输出不是它应该的样子,java,Java,我的代码如下: 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)

我的代码如下:

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
。我的代码有什么问题


我尝试过从浮点转换到整数和双精度,但没有一个对我有效。

计算机不是魔法。它们不能以无限的精度表示数字,因为这需要无限的内存,而内存并不存在。他们使用了一种创造性的解决方案,试图以一种涵盖您想要表示的大多数数字的方式来表示浮点数,而这些数字仍然适合32位(浮点)或64位(双精度)。但这确实意味着这是不精确的。一个双精度浮点数实际上只能表示有限数量的特定数字,如果你试图让一个数字表示一个不属于这些数字的数字,你就会得到它能表示的最接近它的数字

那么,哪些数字可以表示,哪些数字不能表示?这是非常棘手的,因为计算机在基数2下工作,而我们人类倾向于在基数10下思考

这导致了两个重要的教训:

  • 无论何时“呈现”双精度或浮点值,即向用户显示或出于任何其他原因将其转换为字符串,都必须向计算机指定要查找的内容。“只打印它”是不行的,如果您尝试这样做(例如,使用
    System.out.println(someDouble);
    计算机只是猜测,通常猜错了。下面是正确的方法:
    System.out.printf(“%.2f\n”,someDouble)
    或者如果您不想打印,但要转换为字符串,
    string.format(%.2f,someDouble)
    :您告诉java打印/字符串化它,使逗号后最多有2位数字。如果2.7表示为2.6999999999852,它仍将打印2.7,因为这是最接近2.6999999999852的逗号字符串后不超过2位数字

  • 如果你想保证精确性(在处理金钱问题时通常是个好主意!!),完全不要使用double或float。通常的货币解决方案是使用
    int
    long
    存储美分,而不是欧元或美元。有些人建议您使用
    BigDecimal
    ,但我建议您不要这样做,除非您确实知道自己需要它。分割货币很棘手,需要自定义的st策略,甚至是
    BigDecimal
    都不能在3个银行账户中除4美分而不舍入或崩溃。
    BigDecimal
    是一个更合理的想法,当你必须乘以详细数据时,这会带来大量外汇。在你的情况下,如果你需要应用增值税计算,不要麻烦它,坚持使用cENT,以整数或长整数存储

  • 使用
    float
    而不是
    double
    时会得到不同结果的原因是,float只占用32位内存,因此与
    double
    相比,由
    float
    精确表示的数字更少。Java的System.out.println将应用一些舍入(但不会太多)。这种舍入往往不足以隐藏
    浮点值的不精确性


    18.78998464050293
    是与
    18.789984000000004

    的实际答案最接近的数字,但我也尝试在不使用浮点的情况下使用它,但当我将浮点替换为双精度时,总小数会下降,并且会给出4或更少的小数。你真的理解这个链接告诉你的吗?或者更具建设性:你认为那个链接告诉了你什么?你明白浮点数学/二进制表示法是如何工作的吗?对不起,如果我是那样过来的,我是编程新手,坦白说,我不明白他们在说什么,特别是因为我英语说得不流利,抱歉!我觉得我有点不懂现在理解一下,结果是否有可能根据它解决的数学问题的数量而改变,例如,我使用了“double inclusiefBtwLaag=(verkooprijs/100)*顺便说一句,如果我写“double inclusiefBtwLaag=verkooprijs*1,06;”会更准确吗?询问原因,因为我的朋友编写了相同的代码,而我的代码中出现的错误没有在他的代码中显示出来,所以我很困惑到底是什么问题。@MatthewLeonhart如果你的朋友得到了不同的结果,那么你的代码和他的代码就不完全相同了;比较你的代码,看看你在做什么不同,这会很有趣Jesper修正了它,显然我不得不放弃“除以100,然后乘以21”,并不得不用一个已经计算好的数值(即“1.21”)来替换,然后修正了误差!