0

For a homework problem, I was tasked to make an application in java (using Eclipse) to calculate the worth of euro's to Dollars, Pounds and Lira. Pounds and Lira work fine, but for whatever reason when converting euro's Dollars, it leads to a lot of numbers behind the decimal point on certain numbers (Such as 50) The code is in dutch in several places but the general outline should be clear.

I've talked about this with my teacher, but even he couldn't help me with my answer.

import java.util.Scanner;
public class Tests
{
    public static void main(String[] args)
    {
        int keuze;
        double bedrag;
        double factord=1.1;
        double factorp=0.87;
        double factorl=5.38;
        Scanner c = new Scanner(System.in);
        System.out.print("Kies uw valuta: \n 1    -    Amerikaanse 
Dollar\n 2    -    Engelse Pond\n 3    -    Turkse Lira\n");
        keuze = c.nextInt();
        if(keuze == 1)
        {
            System.out.print("Voer het gewenste bedrag in euro's: ");

            bedrag = c.nextDouble();
            System.out.println( bedrag * factord + " Dollar");
        }

My expected result when entering a number (For example) 20, is 22 (Because the factor is 1.1). This causes no problem, but (for example) entering 50, it leads to 55.00000000000001.

  • Not all values can be represented with doubles or 'floating point numbers' because of internal accuracy problems. This is why you sometimes see these approximated numbers when using them. I would suggest using a BigDecimal, this way you can choose the number of decimals to be used. The link posted by Jan is an excellent reading on the 'why' question! – TheWhiteRabbit Sep 20 '19 at 08:51
  • 1
    already [commented some days ago](https://stackoverflow.com/questions/57954475/large-float-and-double-numbers-in-java-printing-persisting-incorrectly-is-this#comment102321750_57954475) (duplicate?): have a look at [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html), one of the firsts paragraphs about Rounding Errors reads: "Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation." – user85421 Sep 20 '19 at 08:54

2 Answers2

2

It's depend on how many place you want to display in your output. You have to format these according to your need. Below code use DecimalFormat to perform these action.

import java.math.RoundingMode;
import java.text.DecimalFormat;

public class DecimalExample {

    private static DecimalFormat df2 = new DecimalFormat("#.##");

    public static void main(String[] args) {

        double input = 3.14159265359;
        System.out.println("double : " + input);
        System.out.println("double : " + df2.format(input));    //3.14

        // DecimalFormat, default is RoundingMode.HALF_EVEN
        df2.setRoundingMode(RoundingMode.DOWN);
        System.out.println("\ndouble : " + df2.format(input));  //3.14

        df2.setRoundingMode(RoundingMode.UP);
        System.out.println("double : " + df2.format(input));    //3.15

    }

Output

double : 3.14159265359
double : 3.14
double : 3.14
double : 3.15
SSP
  • 2,650
  • 5
  • 31
  • 49
  • Although BigDecimal seems to be the way to go for currency, given the answers on related questions, I like the focus on deciding what precision you need for your particular application and thinking about [memory and performance](http://java-performance.info/bigdecimal-vs-double-in-financial-calculations/) trade offs. – a2k42 Sep 20 '19 at 10:32
2

You should use BigDecimal:

public static void main(String[] args) {
    int keuze = 1;
    BigDecimal bedrag;
    BigDecimal factord = BigDecimal.valueOf(1.1);
    BigDecimal factorp = BigDecimal.valueOf(0.87);
    BigDecimal factorl = BigDecimal.valueOf(5.38);
    Scanner c = new Scanner(System.in);
    System.out.print("Kies uw valuta: \n 1    -    AmerikaanseDollar\n 2 - Engelse Pond\n 3 - Turkse Lira\n");
    if(keuze == 1) {
        keuze = c.nextInt();
        System.out.print("Voer het gewenste bedrag in euro's: ");

        bedrag = BigDecimal.valueOf(c.nextDouble());
        System.out.println(bedrag.multiply(factord) + " Dollar");
    }
}

Output:

Voer het gewenste bedrag in euro's: 50
55.00 Dollar

Have a look at : Double vs. BigDecimal

Prashant
  • 4,775
  • 3
  • 28
  • 47
i.bondarenko
  • 3,442
  • 3
  • 11
  • 21