Skip to Content
Technical Articles
Author's profile photo Matthew Billingham

0.1 + 0.2 does not equal 0.3

Here’s a little bit of code:

REPORT.

DATA a TYPE f.
DATA b TYPE f.
a = '0.1'.
b = '0.2'.
DATA c TYPE f.
c = a + b.
WRITE / c.

Output is… 3,0000000000000004E-01 (i.e. 0.300 000 000 000 000 04)

Add a couple more WRITE statements and you might begin to see what’s going on.

1.0000000000000001E-01
2.0000000000000001E-01
3.0000000000000004E-01

For a full explanation (and what put me onto this) see here. It’s kind of obvious, once you think about, but it never really occured to me!

Assigned Tags

      5 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Juwin Pallipat Thomas
      Juwin Pallipat Thomas

      This reminded me of my question, that we discussed years ago 😀

      https://answers.sap.com/questions/8611424/sap---bad-math-student.html

      Author's profile photo Manfred Klein
      Manfred Klein

      The 'real' fun begins when You have to compare 0.1(32bit) with 0.1(64bit). When casting the 0.1(32bit) to 0.1(64bit) binary zeroes are added. Those are different to decimal zeroes, what You would actually need. The quick and extremely dirty workaround is to turn the 0.1(32bit) into a string and using a 'ascii2double'-function to turn it into a 0.1(64bit). Now You can compare them. Or simply turn both numbers to strings and compare those. It's very dirty because string functions are 'expensive' in terms of runtime.

      What a colleague of mine suggested is to compare floats not directly but define a range of acceptance. 0.1(32bit) is accepted as equals to 0.1(64bit) if 0.1(64bit) is smaller than (0.1(32bit) casted to 64bit) + 0.00001(64bit) AND greater than (0.1(32bit) casted to 64bit) - 0.00001(64bit). That's the more scientific way but also way more complicated to handle.

      It get's awkward if You have to compare 0.00001(32bit) with 0.00001(64bit). Then You should first multiply both numbers to get Your figures closer to the decimal sign and then repeat the procedure from above. Why is that? Floats get more and more error prone the further You move away from the decimal sign.

      Had this 'fun' in Java. So it's written in pseudo code, here. I'm sure there are more than enough guys around here which could turn this in ABAP code, in no time.

      Why is all of this mess happening anyhow? Long story short: You have unlimited numbers alone between 0.1 and 0.3. And You have only either 2 to the power of 32 or 64 combinations to represent all the floats from minus infinity to plus infinity. As You can see in this article, the error happens the moment You define 0.1 as float.

       

      Have fun,

      Manfred

      Author's profile photo Shai Sinai
      Shai Sinai

      Interesting.

      In what case you use to have both floats in 32bit and in 64bit representation in the same program?

      Author's profile photo Manfred Klein
      Manfred Klein

      As I said, I had this in Java. Got values from 2 different data sources. One was 32 bit and one was 64 bit.

      Author's profile photo Jacques Nomssi Nzali
      Jacques Nomssi Nzali

      having implemented abapScheme, I know you cannot use numbers in Scheme without understanding Exactness. There is a nice discussion in section 6.2. of the specification. I like the conclusion

      Thus inexactness is a contagious property of a number.

      From this we can expect the result of an operation with inexact numbers to be inexact

      (+ 0.1 0.2) => 0.30000000000000004

      The output depends on the implementation (this is from Racket, abapScheme would display 0.3).

      Note Scheme's numerical tower distinguishes between

      • mathematical numbers (e.g. the number 3),
      • the Scheme number that attempt to model them (integer 3, rational 1/2, real 0.5, complex 0.5+3i, implementations may distinguish special numbers called positive infinity, negative infinity, NaN and negative zero) and
      • the machine representations used to implement the numbers
      • the notation used to write numbers.

      In Scheme, it is possible to use rationals for an exact representation:

      (+ 1/10 2/10) => 3/10

      In ABAP you achieve the same with a dedicated P type:

      "TYPES number TYPE f.
      TYPES number TYPE p DECIMALS 2.
      
      DATA a TYPE number.
      DATA b TYPE number.
      a = '0.1'.
      b = '0.2'.
      DATA c TYPE number.
      c = a + b.
      WRITE / c.

      => 0,30