-2

I’m working on a project at the java and can’t get a very important method to work

I have tried multiple solutions many from similar questions in stackoverflow none of the answers seems to work for may case

What I need is a simple method that will get a double and no matter what is the value of the double as long as there is more than two digits after the dot it will return the same number with only the first two digits after the dot

For example even if the input is “-3456.679985432333” The output would be “-3456.67” and not “-3456.68” like other solutions gave me

The closest solution that seems to work was

public static double round (double d) {
    d = (double) (Math.floor(d * 100)) / (100);
    return d;
}

Yet it did failed when the input was “-0.3355555555555551” the output was “-0.34” and not “-0.33” as expected I have no idea why did it fail and I’m out of solutions with only a few hours left for this project.

Edit: the fix I found was simple and worked great

  public static double round (double d){ 
      if (d>0) return (double) (Math.floor(d*100))/100;
      else 
      {
      return (double) (Math.ceil(d*100))/100;
      }
}

Anyway thanks for everyone that explained to me what was wrong with my method and I will make sure to try all of your solutions

TomZe
  • 21
  • 1
  • 7
  • Take a look at this, Hope this [helps](https://stackoverflow.com/questions/14845937/java-how-to-set-precision-for-double-value) – Amr Adel Nov 19 '17 at 18:13
  • You will always experience such issues when working with decimal values. They can not be represented with infinite precision. Especially when you are intentionally using such a *corner value*. What happens is that the internal precision is limited and the value is represented as something below `.5`, thus rounding downwards. – Zabuzard Nov 19 '17 at 18:14
  • 2
    nit: you shouldn't name your function `round`, since it's not rounding. – Krease Nov 19 '17 at 18:16
  • you have to use `DecimalFormat` to get what you want as one of the answers already tells you. –  Nov 19 '17 at 18:26

4 Answers4

3

Explanation

Java is working correct. It's rather that floor returns the first integer that is less than (or equal) to the given value. It does not round towards zero.

For your input -0.335... you first multiply by 100 and receive -33.5.... If you now use floor you correctly receive -34 since its a negative number and -34 is the first integer below 33.5....


Solution

If you want to strip (remove) everything after the decimal you need to use ceil for negative numbers. Or use a method which always rounds towards zero, i.e. the int cast:

public static double round (double d) {
    d = (double) ((int) (d * 100)) / (100);
    return d;
}

(also see round towards zero in java)


Better alternatives

However there are dedicated, better, methods to achieve what you want. Consider using DecimalFormat (documentation):

DecimalFormat formatter = new DecimalFormat("##.##"); //
formatter.setRoundingMode(RoundingMode.DOWN); // Towards zero
String result = formatter.format(input);

Or any other variant, just search for it, there are plenty of questions like this: How to round a number to n decimal places in Java

Zabuzard
  • 20,717
  • 7
  • 45
  • 67
  • I’m certainly not saying the method Math.floor is not working I’m saying that the whole method isn’t giving the result I want is there any thing that will simply cut the digits after the first two digits after the dot ? – TomZe Nov 19 '17 at 18:27
  • @user8962148 Yeah, as explained `floor` isn't what you are looking for. It does **not** round towards zero. – Zabuzard Nov 19 '17 at 18:28
1

Something like this would suffice:

public static double truncate(double input) {
       DecimalFormat decimalFormat = new DecimalFormat("##.##");
       decimalFormat.setRoundingMode(RoundingMode.DOWN);
       String formatResult = decimalFormat.format(input);
       return Double.parseDouble(formatResult);
}

returns:

-3456.67

and

-0.33

respectively for both examples provided.

Ousmane D.
  • 50,173
  • 8
  • 66
  • 103
0
public static double CustomRound(double number, int digits)
{
    if (digits < 0)
        throw new IllegalArgumentException();

    long f = (long)Math.pow(10, digits);

    number = number * f;

    long rnd = Math.round(number);

    return (double)(rnd / f);
}

An alternative approach:

public static double round(double number, int digits)
{
    if (digits < 0)
        throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(digits, RoundingMode.HALF_UP);

    return bd.doubleValue();
}
Tommaso Belluzzo
  • 21,428
  • 7
  • 63
  • 89
0

you are able to do this, all you need to do is: number * 10 or (100), then convert to a int, then back to double and / 10 (or 100). 10 = for 1 number after digit, 100 = for 2 (if i remember correctly).