3

When executing the following code:

public class FPoint {
    public static void main(String[] args) {
        float f = 0.1f;
        for(int i = 0; i<9; i++) {
            f += 0.1f;
        }
        System.out.println(f);
    }
}

The following output is displayed:

1.0000001

But output should be 1.0000000, right? Correct me if I'm wrong..!!

Gokul Nath KP
  • 15,485
  • 24
  • 88
  • 126
  • 5
    Any reason for down-voting...?? – Gokul Nath KP Sep 30 '13 at 06:50
  • 0.1 cannot be expressed exactly in binary, as such this will always be an approximation – Richard Tingle Sep 30 '13 at 06:51
  • possible duplicate of [Why is the last number (1) printed?](http://stackoverflow.com/questions/18646003/why-is-the-last-number-1-printed) – raina77ow Sep 30 '13 at 06:52
  • @RichardTingle 0.1 can be represented in binary, but not using floating points. – logoff Sep 30 '13 at 06:53
  • You may find this useful http://stackoverflow.com/questions/19078531/subtracting-two-decimal-numbers-giving-weird-outputs/19078568#19078568 – Richard Tingle Sep 30 '13 at 06:53
  • possible duplicate of [Precision error with floats in Java](http://stackoverflow.com/questions/6713673/precision-error-with-floats-in-java) – Marco Forberg Sep 30 '13 at 06:53
  • 1
    @logoff really, how? I thought it was similar to 1/3 which cannot be expressed exactly in decimal – Richard Tingle Sep 30 '13 at 06:57
  • @RichardTingle using BigDecimal for instance in Java (with sacle = 1 and integer = 1, 0.1). 1/3 is different, because it has infinite digits in decimal representation (0.3333333...), but it can be represented using fractional numbers too. – logoff Sep 30 '13 at 07:01
  • @logoff I believe big decimal uses the decimal system; hence its slowness as its non native. The numbers 1/10 and 1/3 are no different. 1/3 can be exactly represented in base 3 as 0.1 – Richard Tingle Sep 30 '13 at 07:04
  • @RichardTingle I don't think so, you need a rational numbers to represent 1/3 like [Apache Commons Math Fraction](http://commons.apache.org/proper/commons-math/userguide/fraction.html), not BigDecimal. try this: `BigDecimal one = new BigDecimal(1); BigDecimal three = new BigDecimal(3); BigDecimal third = one.divide(three);`. it is a number that can not be represented without precision error. – logoff Sep 30 '13 at 07:41
  • @logoff thats because 1/3 cannot be expressed exactly in base 10. BigDecimal uses base 10. There is nothing special about base 10 except that we have 10 fingers – Richard Tingle Sep 30 '13 at 07:50
  • @RichardTingle your comment "0.1 cannot be expressed exactly in binary, as such this will always be an approximation" is wrong, it is possible to represent 1/3 in binary, but not using BigDecimal or floating point numbers in base 10. that's the motivation of my answers. – logoff Sep 30 '13 at 08:02
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/38317/discussion-between-richard-tingle-and-logoff) – Richard Tingle Sep 30 '13 at 08:03

4 Answers4

8

0.1 is not really "0.1" with IEEE 754 Standard.

0.1 is coded : 0 01111011 10011001100110011001101 (with float number)

  • 0 is the sign (= positive)
  • 01111011 the exponent (= 123 -> 123 - 127 = -4 (127 is the bias in IEEE 754))
  • 10011001100110011001101 the mantissa

To convert the mantissa in decimal number we have 1.10011001100110011001101*2^-4(base2) [the 1.xxx is implicit in IEEE 754]

= 0.000110011001100110011001101(base2)

= 1/2^4 + 1/2^5 + 1/2^8 + 1/2^9 + 1/2^12 + 1/2^13 + 1/2^16 + 1/2^17 + 1/2^20 + 1/2^21 + 1/2^24 + 1/2^25 + 1/2^27 (base10)

= 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + 1/131072 ...(base10)

= 0.10000000149011612(base10)

Fabien Sa
  • 9,135
  • 4
  • 37
  • 44
4

Much like certain real numbers like 1/3 cannot be expressed exactly in our decimal system certain numbers like 1/10 cannot be exactly expressed in in binary.

1/3=(decimal)0.33333333333 (3) recurring  
1/10=(binary)0.00011001100 (1100) recurring 

Because we are so familiar with decimal it seems obvious that 1/3 cannot be exactly represented, but to someone with a base 3 number system this would seem like a major limitation to decimal;

1/3=(base 3)0.1

As such 1/10 is inexactly represented within the float and by adding multiple inexact numbers together you get an inexact answer.

It is within this context that you should interpret the floating point errors. If you have a number that is exactly representable within decimal but not within binary then you may find BigDecimal useful. But you should not consider BigDecimal to be better than floating point numbers; it just has a different set of numbers it can and can't represent exactly; the set you're used to. BigDecimal also attempts to use the decimal counting system on a binary processor; as such its calculations are less efficient that double/float based calculations

Richard Tingle
  • 16,906
  • 5
  • 52
  • 77
0

If you need exact computation, like when you work with very sensitive data, don't use float or double, their representation in binary uses approximations. Check this article for some nice explanations.

aUserHimself
  • 1,589
  • 2
  • 17
  • 26
  • 1
    This is not why floating point is problematic for some uses. **All** numerical arithmetic systems are necessarily approximate. They differ only in the natures of their approximations. BigDecimal approximates 1/3. Integer arithmetic approximates most division results (e.g. `5/3*3` does not produce 5). – Eric Postpischil Sep 30 '13 at 10:50
  • You are right, when I said `exact computation` I thought of the fact that a `BigDecimal` can represent a real number more accurate since we can specify its precision and rounding mode. – aUserHimself Oct 02 '13 at 08:52
-1

It is a common misunderstanding. This kind of "errors" are related with floating point data structures: read this. You can use a double in this case to get more precision.

logoff
  • 3,347
  • 5
  • 41
  • 58