[英]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。
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不能精确地表示浮点。
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.