Java,大十进制。除法问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/905795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java, BigDecimal. Problems with division
提问by gonso
I'm trying to calculate a percentage "factor". That is, given a 20%, convert it into 0.2 (my intention is to later multiply values by that and get the 20% of the values).
我正在尝试计算一个百分比“因子”。也就是说,给定 20%,将其转换为 0.2(我的目的是稍后将值乘以该值并获得 20% 的值)。
Anyway, the question is related with this piece of code:
无论如何,问题与这段代码有关:
public static void main(String[] args) {
int roundingMode = BigDecimal.ROUND_FLOOR;
BigDecimal hundred = new BigDecimal("100");
BigDecimal percentageFactor = null;
BigDecimal percentage = new BigDecimal("20");
BigDecimal value = new BigDecimal("500");
percentageFactor = percentage.divide(hundred, roundingMode);
float f = percentage.floatValue() / hundred.floatValue();
f = value.floatValue() * f;
BigDecimal aux = value.multiply(percentageFactor);
System.out.println("factor:"+percentageFactor.toString());
System.out.println("final falue:"+aux.toString());
System.out.println("Float Value:"+f);
}
I would expect the outcome of this to be something like:
我希望这样做的结果是这样的:
factor: 0.2
final value: 100
float value: 100
but instead percentage.divide(hundred, roundingMode);
is returning zero, an hence I get:
而是percentage.divide(hundred, roundingMode);
返回零,因此我得到:
factor:0
final falue:0
Float Value:100.0
What am I doing wrong? How can I divide two big decimals properly?
我究竟做错了什么?如何正确划分两个大小数?
By the way, I'm using BigDecimal
because I will be calculating monetary percentages, so I want control regarding rounding.
顺便说一下,我使用的BigDecimal
是因为我将计算货币百分比,所以我想要控制四舍五入。
回答by dfa
you probably want to use ROUND_UP as rounding mode
您可能想使用ROUND_UP 作为舍入模式
回答by paxdiablo
The scale of new BigDecimal("20")
is zero because you've got no decimal point in there. That means that your percentage.divide(hundred, BigDecimal.ROUND_FLOOR)
will produce zero (it's effectively int(20/100)
or 0
).
的比例new BigDecimal("20")
为零,因为那里没有小数点。这意味着您percentage.divide(hundred, BigDecimal.ROUND_FLOOR)
将产生零(它实际上是int(20/100)
或0
)。
If you really want to do fractional stuff, use new BigDecimal("20.00")
so the scale is set correctly, or use one of the other constructors to set the scale specifically.
如果你真的想做小数的东西,使用new BigDecimal("20.00")
so 比例设置正确,或者使用其他构造函数之一专门设置比例。
Here's the output from that simple change of 20
to 20.00
, complete with your spellink misteak :-)
这是对20
to 的简单更改的输出20.00
,以及您的拼写错误:-)
factor:0.20
final falue:100.00
Float Value:100.0
回答by KarlP
I think that the best solution is to set the requested scale when dividing: In this case perhaps 2.
我认为最好的解决方案是在划分时设置请求的比例:在这种情况下可能是 2。
BigDecimal hundred = new BigDecimal(100);
BigDecimal percentage = new BigDecimal(20);
BigDecimal value = new BigDecimal(500);
BigDecimal percentageFactor =
percentage.divide(hundred,2, BigDecimal.ROUND_HALF_UP);
value = value.multiply(percentageFactor);
System.out.println("final value:"+ value);
final value 100.00
最终值 100.00
(Multiplication is using the scale from the factors (0+2) but it can be specified too.)
(乘法使用因子 (0+2) 的比例,但也可以指定。)
I'd use HALF_UP for accounting (in my legislation) or EVEN (for statistics) for rounding mode.
对于四舍五入模式,我会使用 HALF_UP 进行会计(在我的立法中)或 EVEN(用于统计)。
回答by Peter Lawrey
float has only 6 digits of accuracy and is almost never a good choice, I would suggest you use double instead. (or BigDecimal can be better in some cases)
float 只有 6 位精度,几乎从来都不是一个好的选择,我建议你改用 double。(或 BigDecimal 在某些情况下会更好)
回答by HongYi
The reason factor
is 0 instead of 0.2 in your code is because
代码中的原因factor
是 0 而不是 0.2 是因为
- you've set the RoundingMode to be FLOOR (which means ROUND DOWN), and
- your
percentage
variable has an implicit scale of 0 (anyBigDecimal
s initialised from round number without specifying scale will have scale of 0)
- 您已将 RoundingMode 设置为 FLOOR(这意味着 ROUND DOWN),并且
- 您的
percentage
变量具有 0 的隐式比例(任何BigDecimal
从整数初始化而不指定比例的 s 的比例将为 0)
So when you call divide you are rounding down any decimals and you are maintaining a scale of 0, and hence 0.2 is rounded down to 0.
因此,当您调用除法时,您将四舍五入任何小数,并保持小数位数为 0,因此 0.2 将四舍五入为 0。
To get the correct number, you can either
要获得正确的号码,您可以
- specify the scale explicitly, or
- since you know you are dividing against 100, you can just use the
BigDecimal#divide(BigDecimal)
method instead (without providing scale or RoundingMethod). In your case, the method will not throwArithmeticException
since there is no possibility of non-terminating decimals (think 20 / 100 = 0.2, 20 / 10000 = 0.002 - decimals always terminate when dividing by 100).
- 明确指定比例,或
- 因为您知道要除以 100,所以您可以
BigDecimal#divide(BigDecimal)
改为使用该方法(不提供比例或 RoundingMethod)。在您的情况下,该方法不会抛出,ArithmeticException
因为不可能出现非终止小数(想想 20 / 100 = 0.2, 20 / 10000 = 0.002 - 除以 100 时小数总是终止)。
However, if you're dividing against another number say 3 then you need to specify the scale because there is a possibility of non-terminating decimals (think 10 / 3 = 3.3333333333...)
但是,如果您要除以另一个数字,比如 3,那么您需要指定比例,因为有可能出现非终止小数(想想 10 / 3 = 3.3333333333...)