为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

饮歌长啸 2021-09-12 20:44:59
我的代码如下: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.726400604248045Verkoopprijs inclusief 6% BTW: 18.78998464050293Verkoopprijs inclusief 21% BTW: 21.448944731140134但是代码弄乱了输出中的最后几个小数位。6% 的实际输出应该是:18.789984000000004。我的代码有什么问题?我试过从 float 切换到 int 和 double,但没有一个对我有用。
查看完整描述

1 回答

?
www说

TA贡献1775条经验 获得超8个赞

电脑不是魔法。它们不能以无限精度表示数字,因为这需要不存在的无限内存。他们使用一种创造性的解决方案来尝试以一种涵盖您想要表示的大多数数字的方式来表示浮点数,同时它仍然适合 32 位(浮点数)或 64 位(双精度数)。但这确实意味着它不准确。双精度/浮点数实际上只能表示有限数量的特定数字,如果您试图让一个数字表示不是其中之一的数字,则会得到它可以表示的最接近它的数字。

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

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

  1. 每当您“渲染”双精度或浮点数时,即向用户显示或出于任何其他原因将其转换为字符串时,您必须向计算机指定您要查找的内容。“只是打印它”不会做,如果你尝试这样做(例如,System.out.println(someDouble);计算机只是猜测,通常会猜错。这是正确的方法:System.out.printf("%.2f\n", someDouble)或者如果你不想打印但转换为字符串,String.format("%.2f", someDouble):您告诉 java 打印/字符串化它,以便在逗号后最多获得 2 位数字。如果 2.7 表示为 2.6999999999999999852,它仍会打印 2.7,因为这是最接近的不超过 2 位数字-after-the-comma 字符串表示为 2.6999999999999999852。

  2. 如果您希望保证精度(通常在处理金钱时是个好主意!!),根本不要使用 double 或 float。通常的解决方案是使用intlong存储美分而不是欧元或美元。有些人会建议你BigDecimal改用,但我建议不要这样做,除非你真的知道你需要它。分钱很棘手,需要自定义策略,甚至BigDecimal不能在不四舍五入或崩溃的情况下将 4 美分分到 3 个银行账户。BigDecimal当你必须乘以细节时,这是一个更合理的想法,这会带来很多外汇。在您的情况下,您需要应用增值税计算,不要理会它并坚持使用美分,存储在整数或多头中。

使用float而不是时得到不同结果的原因double是浮点数仅占用 32 位内存,因此floatdouble. Java 的 System.out.println 将应用一些四舍五入(但不多)。这种四舍五入往往不足以隐藏float.

18.78998464050293是与 的实际答案完全一致的最接近的数字18.789984000000004


查看完整回答
反对 回复 2021-09-12
  • 1 回答
  • 0 关注
  • 122 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信