1

I'd like to get the closest number in decimal. The digits behind comma should be the multiplication of 5 (2 numbers behind comma), with 1-3 rounding down to 0, 4-6 round to 5 and 7-9 to 0 and rounding up (increment) the left side of the digit. And also skip the third digit if it's 0.

For example:

4.985 -> 5.0

4.37 -> 4.4

2.14 -> 2.15

4.41 -> 4.4

5.29 -> 5.3

4.17 -> 4.2

2.07 -> 2.1

4.64 -> 4.65

5.21 -> 5.2

2.34 -> 2.35

I've tried this but got wrong in some of the tests.

public static void main(String[ ] args) {
    double[] check = {4.985, 4.37, 2.14, 4.41, 5.29, 4.17, 2.07, 6.64, 5.21, 2.34, 4.89};
    double[] results = {5.0, 4.4, 2.15, 4.4, 5.3, 4.2, 2.1, 6.65, 5.2, 2.35, 4.9};
    for(int i=0; i<check.length; i++){
        double res = getClosestValue(check[i]);
        System.out.println(check[i]+" should be "+results[i]+" got "+res+" so it is "+
                        assertEquals(res, results[i]));
    }
}

public static boolean assertEquals(double a, double b){
    return a==b;
}

public static double getClosestValue(double number) {
    String value = String.valueOf(number).substring(0, 4);
    int firstDigit = Character.getNumericValue(value.charAt(0));
    int secondDigit = Character.getNumericValue(value.charAt(2));
    int lastDigit = Character.getNumericValue(value.charAt(3));
    boolean secondChange = false;
    if (lastDigit <= 3) {
        lastDigit = 0;
    } else if (lastDigit >= 7) {
        lastDigit = 0;
        secondDigit++;
        secondChange = true;
    } else {
        lastDigit = 5;
    }
    if(secondChange){
        if(secondDigit <= 3){
            secondDigit = 0;
        } else if(secondDigit >= 7){
            secondDigit = 0;
            firstDigit++;
        }
    }
    String result = firstDigit + "." + secondDigit + (lastDigit != 0 ? lastDigit : "");
    return Double.parseDouble(result);
}

Result:

  • 4.985 should be 5.0 got 5.0 so it is true
  • 4.37 should be 4.4 got 4.4 so it is true
  • 2.14 should be 2.15 got 2.15 so it is true
  • 4.41 should be 4.4 got 4.4 so it is true
  • 5.29 should be 5.3 got 5.0 so it is false
  • 4.17 should be 4.2 got 4.0 so it is false
  • 2.07 should be 2.1 got 2.0 so it is false
  • 6.64 should be 6.65 got 6.65 so it is true
  • 5.21 should be 5.2 got 5.2 so it is true
  • 2.34 should be 2.35 got 2.35 so it is true
  • 4.89 should be 4.9 got 5.0 so it is false

What is lacking in my code? Are there any better approach to get this?

EDIT: This is not duplicate from the one that marked duplicate, I'm trying to round 2 numbers after comma, not just 1 number

Community
  • 1
  • 1
  • 1
    Possible duplicate of [Double to int rounding normal way from .5](https://stackoverflow.com/questions/21077151/double-to-int-rounding-normal-way-from-5) –  Feb 22 '18 at 06:35
  • 2
    Seems logic not match your requirement. for example, 5.29, the last digit is 9, then change it to 0 and increment the second digit which becomes 3, and set the flag. then, since the flag is set, check the second digit, which is 3 and will be changed to 0, and you get the result 5. That's exactly what you get, but not match your expectation...... – Vincent Zhang Feb 22 '18 at 06:52
  • So your code has issue when the last digit is larger than or equal to 7, and the second digit is lower than 3. And I check your expectations table. you can simply remove the seconddigit <=3 part – Vincent Zhang Feb 22 '18 at 06:55
  • yes, I think that's the problem. but for some cases like 4.98, it works the way it should. what condition do I need to fix that? – Fadel Trivandi Dipantara Feb 22 '18 at 07:00

1 Answers1

1

Your code has the unexpected output when the last digit is larger than or equal to 7, and the second digit is lower than 3. And I check your expectations table.

Based on your comments, I think you can replace the corresponding part code with below ones:

if(secondChange){
    if (secondDigit == 10) {
        secondDigit = 0;
        firstDigit++;
    } 
}
Vincent Zhang
  • 394
  • 2
  • 11