Java 舍入问题

发布于 2024-12-23 16:27:50 字数 368 浏览 2 评论 0原文

基本上,我不明白为什么下面的代码在将 4.35 * 100 = 435.0 转换为 435 的 int 时会输出 434,对吧?

对此的简单解释是什么?这是一个经常出现的问题吗?

你会如何解决这个问题?

public class RoundOffDemo {
    public static void main(String[] args) {
        double price = 4.35;
        int cents = (int) (100 * price); // Should be 435
        System.out.println(cents); // Prints 434!
    }
}

Basically, I don't understand why the code below will output 434 when 4.35 * 100 = 435.0 which is converted to the int of 435, right?

What is the simple explanation for this and is this an issue which crops up often?

How would you get around this?

public class RoundOffDemo {
    public static void main(String[] args) {
        double price = 4.35;
        int cents = (int) (100 * price); // Should be 435
        System.out.println(cents); // Prints 434!
    }
}

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

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

发布评论

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

评论(6

无远思近则忧 2024-12-30 16:27:50

问题是4.35无法用二进制精确表示。所以 4.35 * 100 并不完全是 435.0。 (二进制中的每个分数都是 2 的倒数幂之和,所有这些都是终止小数。不幸的是,0.35 小数具有非终止二进制扩展。因此 4.35 更像是 4.349999...x (其中 x< /em> 是超出的值,一切都为零,这是由机器对浮点数的有限表示提供的。)整数截断然后产生 434。您可以使用Math.round() 来避免这个问题。

The problem is that 4.35 cannot be exactly represented in binary. So 4.35 * 100 is not exactly 435.0. (Every fraction in binary is the sum of inverse powers of 2, all of which are terminating decimals. Unfortunately, 0.35 decimal has a non-terminating binary expansion. So 4.35 is more like 4.349999...x (where x is something beyond which everything is zero, courtesy of the machine's finite representation of floating point numbers.) Integer truncation then produces 434. You can use Math.round() to avoid this problem.

怪异←思 2024-12-30 16:27:50

IMO,使用 BigDecimal 的建议是多余的。对于分,请使用长整型。甚至美国国债也可以通过多美分来偿还。

如果您确实使用浮点数(或双精度数),则在转换为整数时,请根据需要使用 Math.round()、Math.floor() 或 Math.ceil()。

IMO, the suggestions to use a BigDecimal are overkill. For cents, use a long. Even the US National Debt can be covered using a long for cents.

If you do use floats (or doubles), when converting to integers, use Math.round(), Math.floor() or Math.ceil() as appropriate.

枫以 2024-12-30 16:27:50

如果您使用此代码:

System.out.println(price*100); // Prints 434!

您会注意到它的输出是

434.99999999999994

四舍五入为 434

if you use this code:

System.out.println(price*100); // Prints 434!

you notice its output is

434.99999999999994

which rounded is 434

弥繁 2024-12-30 16:27:50

双精度值 4.35 实际上表示为 4.349999999999999。
100 * 4.349999999999999 = 434.9999999999999。
将其转换为 int 值将得到 434。

Double value 4.35 is actually represented as 4.349999999999999.
100 * 4.349999999999999 = 434.9999999999999.
And casting it to int value will give you 434.

终止放荡 2024-12-30 16:27:50

这是浮点运算的结果。正如 @Ted 指出的那样, (int) 转换不是舍入函数,而是截断。

由于您正在处理金钱(从您的变量名称可以明显看出),请使用 BigDecimal 代替。

例如 -

double d = 4.35;
BigDecimal bd = BigDecimal.valueOf(d);
bd  = bd.multiply(new BigDecimal(100));

This is a result of floating point arithmetic. The (int) casting is not a rounding function, but rather a truncation as @Ted points out.

Since you are dealing with money ( as evident from your variable names ) use BigDecimal instead.

For example --

double d = 4.35;
BigDecimal bd = BigDecimal.valueOf(d);
bd  = bd.multiply(new BigDecimal(100));
请远离我 2024-12-30 16:27:50
  1. 在 Java 中不要使用 double/float 进行浮点运算,而应使用 BigDecimal。这是因为Java无法精确表示浮点。

  2. 始终使用 BigDecimal 作为临时变量,这些变量将在以后的计算中进行处理/涉及。仅当您想将值保存到数据库中时,才将这些值转换为 float/double。

  1. Do not use double/float for floating-point arithmetic in Java, use BigDecimal instead. This is because Java cannot represent floating-point precisely.

  2. Always use BigDecimal for temporary variables, which will be processed/involved in future calculations. Convert the values to float/double only if you want to persist them into the database.

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