What actually happens is the computer only has 64 bits to work with. It has to throw away the low order part of any result after every operation. On every calculation you accumulate a little more roundoff error. In the newer Java’s the computer is permitted to secretly retain a few extra bits of accuracy during a short string of calculation, so sometimes they come out more accurate that you would theoretically expect. (They almost never come out more accurate than a newbie expects.) To discourage use of these guard bits, and get reproducibly less accurate results you use the StrictMath library. Unless you really know what you are doing, you must presume the results are never precisely bang on. Don’t count on results that in theory should be integers coming out precisely as integers. Never compare == or !=, check within a tolerance. Keep in mind when you compare > >= < <= the values you are comparing may, as a side effect of calculation, have drifted just above or just below your test limits. Sometimes you may want to include some slop/tolerance in your limits. Java is somewhat better than other languages since it specifies strict IEEE rules. Fortunately, in Java, if a number has a perfect integer floating point representation, and you divide it by another such number that is a factor, the result is guaranteed to be a perfect integer representation.
The other source of the fuzz is accumulating roundoff error from cascaded operations. Further there are errors in trig functions not being bang on 0 or 1 as you expect. This is a result of accumulated roundoff error in evaluating polynomials and in the polynomial approximations themselves used internally to compute the trig functions.
if ( f == 100.00 )say
if ( f > 99.995 )
if ( Math.abs( value - target ) < epsilon )or faster, but more verbose:
if ( value >= target - epsilon && value <= target + epsilon )when the order of magnitude of target is unknown, you might use some slower code like this, presuming target is positive:
if ( Math.abs( value - target ) < epsilon * target )or
if ( value >= target * ( 1 - epsilon ) && value <= target * ( 1+ epsilon ) )
f += 0.001;code
f = i * 0.001;
// to see the IEEE bits inside a float int inside = Float.floatToIntBits ( f ); // to construct a float out of IEEE bits float f = Float.intBitsToFloat ( bits ); // to see the IEEE bits inside a double long inside = Double.doubleToLongBits ( d ); // to construct a double out of IEEE bits double d = Double.longBitsToDouble ( bits );
String Double.toString( double )Java wants to preserve every drop of precision it has, so that if you convert it back with:
double Double.parseDouble( String )you will get back to the precise same binary representation. This is all very well, but from the point of view of humans, the display looks wrong, as if result were slightly inexact and with way too many digits. This also makes the rounding error distressingly visible. To fix it, and create something that looks pleasingly rounded to humans, use java.text.DecimalFormat to limit the number of digits displayed to what you actually want/need.
If you are merely trying to round for internal purposes use Math.round, Math.floor, Math.ceil and Math.rint. Math.round gives a long result, the rest double. You can create variants by adding .5 and multiplying and dividing by powers of ten. There is generally no need to convert to int or long and back.
| Comparison of Pentium Floating Point and Integer Speeds | ||
|---|---|---|
| Operation | Floating Point clocks | Integer Clocks |
| add | 1-3 | 1-3 |
| multiply | 1-3 | 10-11 |
| division | 39-42 | 22-46 |
| convert | 6 (double to long) | 3 (long to double) |
Other odd results you can get from floating point operations include Double. NEGATIVE_INFINITY, Double. POSITIVE_INFINITY and positive and negative 0. There is a similar method for checking for infinity, Double. isInfinite.
0./0. gives NaN, 1./0. gives POSITIVE_INFINITY and -1./0. gives NEGATIVE_INFINITY.
// fast accurate way to cube a number double y = x * x * x;rather than:
// slow, inaccurate way to cube a number double y = Math.pow( x, 3 );Ditto for squaring. Further, if x is an integer, you will get a precise result using only simple arithmetic. If you use: Math.pow you will lose precision. Also use the specialised
// fast way to do a square root double y = Math.sqrt( x );in preference to the general
// slow way to do a square root double y = Math.pow( x, 0.5 );
| Common Floating Point Calculation | |
|---|---|
| Method | Purpose |
| + | addition. |
| - | subtraction. |
| * | mulitplication. |
| / | division, with a fractional result. If you divide by 0/0, 7/0 or overflow the maximum representable number, you won’t get an exception. You will get a special marker result. You can test for it with Math. isInfinite or isNaN. |
Sun’s Javadoc on the abs method : available:
|
absolute value. |
Sun’s Javadoc on the cbrt method : available:
|
cube root. |
Sun’s Javadoc on the ceil method : available:
|
ceiling, next highest integer. |
Sun’s Javadoc on the exp method : available:
|
ex. |
// compute exponent if number were written in scientific notatation int exponent = (int)Math.log10( value ) + 1; // e.g. 12345.0 -> 0.12345E06 -> exponent 6, mantissa 0.123454. |
base 10 exponent were the number written in scrientific notation. Internally number use IEEE binary exponents. |
Sun’s Javadoc on the hypot method : available:
|
hypotenuse, distance from origin to a point: sqrt( x² + y² ). Note if you want to do is compare two distances, you don’t need the sqrt. |
Sun’s Javadoc on the log method : available:
|
natural log, base e log, ln. Not base 10 common logarithm! |
Sun’s Javadoc on the log10 method : available:
|
base 10 log. |
// compute mantissa if number were written in scientific notatation int exponent = (int)Math.log10( value ) + 1; double mantissa = value * Math.pow( 10.0, -exponent ); // e.g. 12345.0 -> 0.12345E06 -> exponent 6, mantissa 0.123454. |
base 10 mantissa were the number written in scientific notation. Internally Java uses IEEE binary exponents. |
Sun’s Javadoc on the max method : available:
|
larger of two numbers. |
Sun’s Javadoc on the min method : available:
|
smaller of two numbers. |
Sun’s Javadoc on the pow method : available:
|
power, ab. |
Sun’s Javadoc on the rint method : available:
|
round to nearest integer. Result is a double that is a integer. |
Sun’s Javadoc on the round method : available:
|
round to nearest integer. Result is an long. |
Sun’s Javadoc on the signum method : available:
|
Returns the signum function of the argument; 0 if == 0, 1.0 if > 0, -1.0 if < 0. The result is a double, not an int as you would expect. |
Sun’s Javadoc on the sqrt method : available:
|
square root. |
![]() |
and suggestions to improve this page to Roedy Green : | ||
| Canadian Mind Products | |||
| mindprod.com IP:[65.110.21.43] | |||
| Your face IP:[38.103.63.62] | The information on this page is for non-military use only. | ||
| You are visitor number 73,082. | Military use includes use by defence contractors. | ||
| You can get a fresh copy of this page from: | or possibly from your local J: drive (Java virtual drive/mindprod.com website mirror) | ||
| http://mindprod.com/jgloss/floatingpoint.html | J:\mindprod\jgloss\floatingpoint.html | ||