0

I've used these posts as reference:

  1. How to round a number to n decimal places in Java
  2. round up to 2 decimal places in java? [duplicate]

After reading through the solutions to these question, I'm still having trouble rounding up to the hundredths place. Here are what I've tried along with their outputs:

BigDecimal

import java.math.BigDecimal;
import java.math.RoundingMode;

public class RaceCarThread extends Thread {

    private static boolean raceNow = false;
    private int iterations;
    private double lapsCompleted;
    private boolean crash;
    private int nbrOfCrashes;
    
    // Default constructor
    public RaceCarThread() {
        super();
    }
    
    // Constructor for custom name
    public RaceCarThread(String name) {
        super(name);
        raceNow = true;
        lapsCompleted = 0;
        crash = false;
        nbrOfCrashes = 0;
    }
    
    public void run() {
        
        while (!(lapsCompleted >= 17)) {
            double randomNum = Math.random();
            BigDecimal bd = new BigDecimal(randomNum).setScale(2, RoundingMode.HALF_EVEN);
            randomNum = bd.doubleValue();
            lapsCompleted = lapsCompleted + randomNum;
            System.out.println(lapsCompleted);
        }
    }   
}
10.31
10.5
11.13
11.850000000000001
12.810000000000002
13.570000000000002
14.200000000000003
15.080000000000004
15.800000000000004
16.200000000000003
16.790000000000003
17.430000000000003

Math.round(randomNum*100d) / 100d

public class RaceCarThread extends Thread {

    private static boolean raceNow = false;
    private int iterations;
    private double lapsCompleted;
    private boolean crash;
    private int nbrOfCrashes;
    
    // Default constructor
    public RaceCarThread() {
        super();
    }
    
    // Constructor for custom name
    public RaceCarThread(String name) {
        super(name);
        raceNow = true;
        lapsCompleted = 0;
        crash = false;
        nbrOfCrashes = 0;
    }
    
    public void run() {
        
        while (!(lapsCompleted >= 17)) {
            double randomNum = Math.random();
            lapsCompleted = lapsCompleted + (Math.round(randomNum * 100d) / 100d);
            System.out.println(lapsCompleted);
        }
    }
}
11.020000000000003
11.730000000000004
12.720000000000004
13.430000000000003
13.930000000000003
14.020000000000003
14.300000000000002
15.210000000000003
15.250000000000002
15.500000000000002
16.32
17.080000000000002

I'm unable to use DecimalFormat due to using the number in calculations.

Edit: The System.out.println(lapsCompleted) is just for checking the values and will be removed once I fix the decimals

Yuchen Ren
  • 287
  • 5
  • 13
Spoonology
  • 73
  • 7
  • 4
    See https://stackoverflow.com/questions/588004/is-floating-point-math-broken for a discussion of how computers work with floating point numbers. – Code-Apprentice May 04 '22 at 23:37
  • 1
    Hint: Whenever you use floating point arithmetics, chances are high that numbers will be slightly 'off', because they're based on fractions. Solution #1: create your own data type that stores an int or long, and its `toString()` method inserts a dot. Solution #2: keep using float or double, but whenever you output the number, always use one of the rounding methods: BigInteger, (x*100)/100, printf(), DecimalFormat. Solution 3: write your own class, which contains a double value, and you implement its `toString()` method to format the double with one of the four methods above. – JayC667 May 04 '22 at 23:47
  • I get it now! Thanks for your help guys. It's much appreciated! – Spoonology May 05 '22 at 00:03
  • 1
    If you've read my answer in your first citation you should have seen that what you are attempting is impossible *a priori,* with proof. – user207421 May 05 '22 at 00:47

1 Answers1

1

If you're going to do calculations with your decimal values, you really need to use BigDecimal throughout. Never trust double or float to give accurate answers to calculations involving decimal values.

Also, when you create a BigDecimal from a double, don't use new BigDecimal(yourDouble), because that just puts the floating point error that's already in your double into the BigDecimal. It's generally much better to use BigDecimal.valueOf(yourDouble), which gives you the decimal value with the least number of decimal places that your double is close enough to. That sounds bad, but it's actually good, because you typically get the value that was used to create the double initially.

For example,

System.out.println(new BigDecimal(0.1)); // prints 0.1000000000000000055511151231257827021181583404541015625
System.out.println(BigDecimal.valueOf(0.1)); // prints 0.1
Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110