1

I am currently trying to write a program which rounds a "double" variable to two decimal places.

I have the method:

DecimalFormat df = new DecimalFormat("#.00");

However, when I apply the method:

double x = df.format(y-z);

I get an error telling me a "double" was expected but a "string" was found.

Any suggestions as to how to fix this?

Thanks!

RNJ
  • 15,272
  • 18
  • 86
  • 131
MrD
  • 4,986
  • 11
  • 48
  • 90
  • 1
    `df.format()` returns a formatted `String` with a rounded value, it doesn't round the `double`. – Keppil Sep 30 '12 at 13:08
  • just use **String.format("%1.2f", d)** and to cast it, use **d = Double.valueOf(String.format("%1.2f", 3.2232))** – user1406062 Sep 30 '12 at 13:19

3 Answers3

1

Try this

@Test
public void test() {
    int f = 100;

    double d = 123.456;
    double temp = d * f;
    double rounded = Math.round(temp);
    double to2dp = rounded / f;

    Assert.assertEquals(123.46, to2dp, 0.00001);
}      

The f = 100 is fro 2dp. You would use f = 10 for 1dp etc

RNJ
  • 15,272
  • 18
  • 86
  • 131
0

If you are using doubles to store/calculate currency values, then you will likely find yourself in a world of pain with rounding. Been there, done that, got the scars.

I highly recommend that you use BigDecimal values for ALL currency values, and do not even involve doubles in the instantiation. Always use the String constructor.

See related questions here and here.

Community
  • 1
  • 1
DuncanKinnear
  • 4,563
  • 2
  • 34
  • 65
0

In a comment on my other answer, Gary Rowe has suggested the use of Joda Money as a solution.

Now while this may be a fine product, and I have to admit that I have not tried it, I am a bit concerned about the following example in their documentation:

// multiplies by 3.5 with rounding
money = money.multipliedBy(3.5d, RoundingMode.DOWN);

Now this is an interesting example because they have used a double amount which can be represented exactly using double precision.

To illustrate this, let's take the following unit test as an example:

    double d1 = 3.5d;
    BigDecimal bd1 = new BigDecimal(d1);
    System.out.println("BD version of " + d1 + " = " + bd1);

    BigDecimal bd2 = new BigDecimal("10000000");
    BigDecimal bd3 = bd2.multiply(bd1);

    System.out.println("Result in bd3 = " + bd3);

This yields the following output:

BD version of 3.5 = 3.5
Result in bd3 = 35000000.0

However, if you change the '3.5d' to '3.4d', you get a very different result:

BD version of 3.4 = 3.399999999999999911182158029987476766109466552734375
Result in bd3 = 33999999.999999999111821580299874767661094665527343750000000

Now the Joda Money classes may deal with this (somehow), but introducing any double precision numbers into the mix is fraught with danger.

Gary, perhaps you could comment about the result of a similar calculation in Joda Money.

DuncanKinnear
  • 4,563
  • 2
  • 34
  • 65
  • Sure. Using the Joda Money class BigMoney the following code snippet achieves what you require: `BigMoney bm1 = BigMoney.parse("USD 3.4"); BigMoney bm3= bm1.multipliedBy(bd2); System.out.println("Result in bm3 = " + bm3);`. The output is `Result in bm3 = USD 34000000.0`. Of course we should also multiply by the decimal amount. So `BigMoney bm3= bm1.multipliedBy(3.4);` provides an output of `Result in bm3 = USD 11.56` which is what you'd expect. – Gary Feb 25 '13 at 10:09
  • As an aside, we use Joda Money as part of the Bitcoin [XChange](https://github.com/timmolter/XChange) project. Bitcoin requires a bare minimum of 12dp and Joda Money has delivered. – Gary Feb 25 '13 at 10:17
  • @Gary Using small enough numbers will usually be OK. Try starting off with `BigMoney bm1 = BigMoney.parse("USD 1,000,000,000,000");` and then multiply it by the 3.4d and round to 4dp. What do you get then? Of course, it may not be USD it could be Columbian Pesos! Now, you've made a conscious decision to use `BigMoney` instead of `Money`. What if you built your system using `Money` and then someone used it with huge amounts? Do the same calculation as above using the `Money` class and see what you get. Bottom line: using `BigDecimal` for ALL currency amounts will ALWAYS calculate correctly. – DuncanKinnear Feb 25 '13 at 20:21
  • Well I ran your suggestion through Joda Money: `BigMoney bm1 = BigMoney.parse("USD 1000000000000.00"); BigMoney bm3= bm1.multipliedBy(3.4); System.out.println("Result in bm3 = " + bm3);` and the result was `Result in bm3 = USD 3400000000000.000` which seems correct to me. While I understand your concerns, do bear in mind that BigDecimal has no concept of a currency code so programming errors where currencies are mixed can arise. If you are able to spend some time with Joda Money and uncover calculation bugs maybe you could report them? – Gary Feb 25 '13 at 22:05
  • @Gary That looks like only 3 dec places. Try 4. And what about my question about using `Money` instead of `BigMoney`? – DuncanKinnear Feb 25 '13 at 22:25
  • When designing a system that will handle monetary values it is reasonable to know in advance the scale of values likely to be used. A small shop will be fine using Money, while a currency exchange will likely require BigMoney. Consequently you can design for the appropriate case. I am satisfied through my own testing that Joda Money is a better solution than just using BigDecimal. Your opinion differs. However, since you have serious concerns about Joda Money, and may have a working test case that demonstrates the flaw, please report it so that the library can be fixed. – Gary Feb 26 '13 at 09:47