views:

2752

answers:

4

Hi.

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).

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:

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.

Thanks in advance.

Gonso.

A: 

you probably want to use ROUND_UP as rounding mode

dfa
+5  A: 

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).

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.

Here's the output from that simple change of 20 to 20.00, complete with your spellink misteak :-)

factor:0.20
final falue:100.00
Float Value:100.0
paxdiablo
+3  A: 

I think that the best solution is to set the requested scale when dividing: In this case perhaps 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

(as the multiplication will keep the scale - it can be overridden in multiply too.)

I'd use HALF_UP for accounting (in my legislation) or EVEN (for statistics) for rounding mode.

KarlP
A: 

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)

Peter Lawrey
If you want control over rounding, you shouldn't be using floating-point numbers at all, neither float nor double. Stick with BigDecimal.
markusk
Often only the final result needs to have controlled rounding, so you have used BigDecimal just for rounding the result (or a simple helper method) This can be significantly simpler and faster.
Peter Lawrey