3

I need to round a small negative number to return 0.0. However, the value I'm getting is minus zero. The following code demonstrates the problem:

double value = -0.000000001;
double roundedValue = Double.valueOf(String.format(Locale.US, "%.4f", value));
System.out.println(roundedValue); // I need the roundedValue to be equal 0.0 (not -0.0)

There is a way to fix this?

João Pedro Schmitt
  • 1,046
  • 1
  • 11
  • 25

3 Answers3

1

You can explicitly handle the negative zero case:

roundedValue = (roundedValue == 0.0 && 1 / roundedValue < 0) ? 0 : roundedValue;

(1 / roundedValue < 0 to check for negative zero, from this answer)


Nit: use Double.parseInt rather than valueOf, to avoid the unnecessary boxing and immediate unboxing.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
1

First, you have to realize that double values are semantically different from integers. They are imprecise, so there is always ever-so-slight error in every double value. The error, however, is small, but in unfortunate case it could be on the other side of zero - technically correct, but not what you want. This understanding is essential; if you need digit-exact arithmetic, you shouldn't be using doubles anyway, but integers/longs. Part of IEEE specification for double values also defines "negative zero", "NaN", "infinity" and so on, so technically the software is correct, but you are not using it the right way for what you want to achieve.

Second, like other people already mentioned, never use string formatting for rounding. If you need 4 decimal places, a much better way is to multiply the number by 10000, take floor/round of it and divide it by 10000 again. However, due to the facts mentioned above, you might again get some small decimal off (such as the 15th decimal digit).

On the other hand, if you just want to get rid of "rounding noise" which is sufficiently close to zero, you can also use this approach which is very robust:

if (Math.abs(x) < 0.000001d) x = 0d;
jurez
  • 4,436
  • 2
  • 12
  • 20
0

Much convenient would be:

double roundedValue = value < 0 ? (Math.ceil(value) == -0 ? 0 : Math.ceil(value)) : value;

In this case, you are going to preserve - values: for example -1.5 the result would be -1, but -0.00000001 is 0.0.

smithnblack
  • 505
  • 7
  • 17