3

Its a classic problem: your legacy code uses a floating point when it should really be using n integer. But, its to expensive to change every instance of that variable (or several) in the code. So, you need to write your own rounding function that takes a bunch of parameters to improve accuracy and convert to an integer.

So, the basic questions is, how do floating point numbers round when they are made in java? the classic example is 0.1 what is often quoted as rounding to 0.0999999999998 (or something like that). But does a floating point number always round down to the next value it can represent when given an integer in Java? Does it round down it's internal mantissa to efficiently round down its absolute value? Or does it just pick the value with the smallest error between the integer and the new float?

Also is the behavior different when calling Float.parseFloat(String) when the String is an integer like "1234567890"? And is the behavior also the same when String is a Floating point with more precision than the Float can store.

Please note that I use floating point or reference Float, I use that interchangeably with Double. Same with integer and long.

Erik Helleren
  • 1,481
  • 1
  • 10
  • 7
  • 1
    There is no need to "round" an integer when converting to floating point. Worst case is when the number of significant bits in the integer exceeds the number of fraction bits in the float form, but that's only a problem for fairly large numbers. – Hot Licks Jul 21 '14 at 18:49
  • possible duplicate of [Floating Point Casting in Java](http://stackoverflow.com/questions/24853428/floating-point-casting-in-java) – Hot Licks Jul 21 '14 at 18:51

1 Answers1

5

how do floating point numbers round when they are made in java?

Java truncates (rounds towards zero) when you use the construct (int) d where d has type double or float. If you need to round to the nearest integer, you can use the line below:

int a = (int) Math.round(d);

the classic example is 0.1 what is often quoted as rounding to 0.0999999999998 (or something like that).

The issue you allude to does not exist with integers, which are exactly representable as double (for those between -253 and 253). If the number you are rounding comes from previous computations that should have produced an integer but may not have because of floating-point rounding errors, then (int) Math.round(d) is likely the solution you should use. It means that you will get the correct integer as long as the cumulative error is not above 0.5.

your legacy code uses a floating point when it should really be using n integer. But, its to expensive to change every instance of that variable (or several) in the code.

If the computations producing the double d are only computations +, -, * with other integers, producing intermediate results between -253 and 253, then d automatically contains an integer (it is exact because the floating-point computations involved are exact, and it is an integer because the exact result is an integer), and you can convert it with the simpler (int) d. On the other hand, if division or non-integer operands are involved, then you should not lightly change the type of d, because it would change the results of these computations.

Also is the behavior different when calling Float.parseFloat(String) when the String is an integer like "1234567890"?

This will produce a float whose value is the nearest representable single-precision value to the rational 1234567890. This happens to be 1234567936.0f.

And is the behavior also the same when String is a Floating point with more precision than the Float can store.

Technically, “0.1” is more precision than Float can store. Also, technically, the previous example 1234567890 is also more precision than Float can store. The behavior is the same: Float.parseFloat("0.1") produces the nearest float to the rational number 0.1.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • So, just to be clear, when going from a large int to a float (lower case) in Java, it will use the nearest number a float can represent. And the same goes for long to double. Also, do you have a reference because it might have more info that's helpful to me and others with a similar problem or question. – Erik Helleren Jul 21 '14 at 23:08
  • Yes. Yes. Java follows the principles of the IEEE 754 standard, which says that base conversions (decimal <-> binary) should be according to the current rounding mode. For the conversion from floating-point to integer (by truncation), Java follows C tradition, which predates the IEEE 754 standard. Finally, don't worry for others with a similar problem or question, they won't read this answer any more than you read the metric ton of existing documentation, including the Java Language definition, the Wikipedia pages on floating-point, … – Pascal Cuoq Jul 21 '14 at 23:17
  • 2
    The Java Language Specification, [5.1.2. Widening Primitive Conversion](http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.2) says "A widening primitive conversion from int to float, or from long to float, or from long to double, may result in loss of precision - that is, the result may lose some of the least significant bits of the value. In this case, the resulting floating-point value will be a correctly rounded version of the integer value, using IEEE 754 round-to-nearest mode (§4.2.4)." – Patricia Shanahan Jul 22 '14 at 00:52
  • 1
    Downvoter, I would be delighted to hear what fault you find with this answer. – Pascal Cuoq Aug 09 '14 at 16:18