简体   繁体   English

Java四舍五入问题

[英]Java Rounding Off Issue

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? 基本上,我不明白为什么当4.35 * 100 = 435.0转换为435的int时,下面的代码会输出434,对吧?

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!
    }
}

The problem is that 4.35 cannot be exactly represented in binary. 问题是4.35无法用二进制表示。 So 4.35 * 100 is not exactly 435.0. 所以4.35 * 100并不完全是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. (二进制中的每个分数都是2的反幂之和,所有这些都是终止小数。不幸的是,0.35十进制有一个非终止的二进制扩展。所以4.35更像是4.349999 ... x(其中x是超出的一切都是零,礼貌的机器的浮点数的有限表示。)整数截断然后产生434.你可以使用Math.round()来避免这个问题。

IMO, the suggestions to use a BigDecimal are overkill. IMO,使用BigDecimal的建议是过度的。 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. 如果使用浮点数(或双精度数),则在转换为整数时,请根据需要使用Math.round(),Math.floor()或Math.ceil()。

This is a result of floating point arithmetic. 这是浮点运算的结果。 The (int ) casting is not a rounding function, but rather a truncation as @Ted points out. (int )转换不是舍入函数,而是@Ted指出的截断。

Since you are dealing with money ( as evident from your variable names ) use BigDecimal instead. 由于您正在处理货币(从您的变量名称中可以明显看出),请使用BigDecimal。

For example -- 例如 -

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

if you use this code: 如果您使用此代码:

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

you notice its output is 你注意到它的输出是

434.99999999999994 434.99999999999994

which rounded is 434 四舍五入是434

Double value 4.35 is actually represented as 4.349999999999999. 双值4.35实际表示为4.349999999999999。 100 * 4.349999999999999 = 434.9999999999999. 100 * 4.349999999999999 = 434.9999999999999。 And casting it to int value will give you 434. 并将其转换为int值将给你434。

  1. Do not use double/float for floating-point arithmetic in Java, use BigDecimal instead. 不要在Java中使用double / float进行浮点运算,而是使用BigDecimal。 This is because Java cannot represent floating-point precisely. 这是因为Java不能精确地表示浮点。

  2. Always use BigDecimal for temporary variables, which will be processed/involved in future calculations. 始终将BigDecimal用于临时变量,这些变量将在未来的计算中处理/参与。 Convert the values to float/double only if you want to persist them into the database. 如果要将值保留到数据库中,则仅将值转换为float / double。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM