2

I have a simple calculation that uses doubles but I'm getting an unexpected result and I can't understand why?

import java.util.Scanner;
public class VersatileSnitSoft {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Scanner myScanner = new Scanner(System.in);
        double amount;
        System.out.print("What’s the price of a CD-ROM? ");
        amount = myScanner.nextDouble();
        amount = amount + 25.00;
        System.out.print("We will bill $");
        System.out.print(amount); 
        System.out.println(" to your credit card.");

    }

}

If I enter 2.99 the result I get is..

We will bill $27.990000000000002 to your credit card.
tatty27
  • 1,553
  • 4
  • 34
  • 73
  • You should not use floats or doubles for any calculation where you need absolute precision - any software dealing with financial transactions being a perfect example! I believe Java offers alternative numeric types to counter this - it might be worth reading into floating-point arithmetic too. – MickMalone1983 May 23 '13 at 13:46
  • 1
    FYI. This is how 2.99 is represented in a double: http://www.binaryconvert.com/result_double.html?decimal=050046057057 The result is just an approximation; 2.99 can't be represented using given number of mantissa bits. – david a. May 23 '13 at 13:48

4 Answers4

11

You cannot represent decimal values precisely whilst operating on doubles (or floats). Use BigDecimal instead.

Edit (2)

Example here:

BigDecimal amount = new BigDecimal("2.99");
amount = amount.add(new BigDecimal("25.00"));
System.out.println(amount.toString());

Ouput:

27.99
Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
Mena
  • 47,782
  • 11
  • 87
  • 106
  • Thanks for that, however, I am fiarly new to Java and I don't understand why to use BigDecimal, it isn't a type I've seen before – tatty27 May 23 '13 at 13:45
  • 1
    You can fin additional references on item 48 of Effective Java. http://books.google.com/books?id=ka2VUBqHiWkC&lpg=PA219&ots=yYIoLft3N4&dq=effective%20java%20bigdecimal&pg=PA218#v=onepage&q=effective%20java%20bigdecimal&f=false – Elmer May 23 '13 at 13:45
2

Doubles (floating-point values in general) cannot always represent exactly what we think of intuitively as a precise value. This is because of the way in which floats are stored, and can vary from machine to machine and language to language. When you try to store 2.99, the actual value that is stored may be very slightly different (e.g. 2.990000000000002). This question gives a decent, quick overview of why.

You should therefore (as it says through the link) never use floating-point primitives to represent currency. Either use BigDecimal, or keep track of two integers yourself (e.g. int dollars; and int cents;).

Community
  • 1
  • 1
Henry Keiter
  • 16,863
  • 7
  • 51
  • 80
1

use DecimalFormat to display 2 digit after whole number

  DecimalFormat f = new DecimalFormat("##.00");
   String amt=f.format(amount);
   System.out.print("We will bill $");
    System.out.print(amt); 

http://www.browxy.com/SubmittedCode/21519

Francis Stalin
  • 439
  • 1
  • 4
  • 14
0

I believe this question has been asked a million times. You can find a good and quick description of it here Why not use Double or Float to represent currency?

If you are just fooling around and you want it to print properly use

String prettyNumber = String.format("%.2f", doubleNumber); 

Which is going to print 2 floating points. It will look correct, but it is only correct if precision (in the magnitude of 10^-16 or so) is not of interest to you.

Community
  • 1
  • 1
alianos-
  • 886
  • 10
  • 21