Values not always same
(1) By HB9FIH on 2022-06-21 16:05:36 [link] [source]
Work with Lazarus and SQLite3 - in program code I created a new db and within a new Table with a field REAL. I insert values by hand into the connected dbGrid. Post and Refresh but the value is not always the same. Input 12.88 - after shows 12.880000000000001 Input 12.77 - after shows 12.77 Input 12.11 - after shows 12.019999999999999 Input 12.01 - after shows 12.01 Whats the reason ? Its the result from SELECT * FROM tbl1 Field can have different names so * is to use. Generally I have some problems with formatting any output. I am a beginner in SQLite and would make some experiences now. (earlier experienced Delphi programmer but dbf/ntx/nsx databases) TNX Erich
(2) By Stephan Beal (stephan) on 2022-06-21 16:14:19 in reply to 1 [source]
Work with Lazarus and SQLite3 - in program code I created a new db and within a new Table with a field REAL.
Here's one of many, many articles which cover the topic:
Why is 0.1 + 0.2 Not Equal to 0.3 in Most Programming Languages?
Which says:
After doing a lot of research and math, I concluded this is not an error. This is math: floating-point arithmetic.
This topic comes up on the forum very often, so searching through older forum posts will reveal lots of details about why relying on floating-point precision will lead to issues like the one you're seeing.
(7) By Tim Streater (Clothears) on 2022-06-21 17:07:07 in reply to 2 [link] [source]
Might I suggest that a sufficient response for this question be made one of the FAQ answers at the SQLite website? Then any requester can simply be pointed at that.
I discovered this truth about floats the hard way in 1965, when writing my first program: to obtain square roots using Newton's method.
(3) By Chris Locke (chrisjlocke1) on 2022-06-21 16:35:27 in reply to 1 [link] [source]
Whats the reason ?
0.1 can't be stored in a binary value - same way if you cut an apple into thirds, you get 0.33, 0.33 and 0.33 of an apple ... which is 0.99 .. where is the .01? (and don't say on the knife...)
Either accept 12.8800000001 and round up (or down) to get to 12.88, or store 1288 in the database and divide by 100 when you need the real (no pun intended) figure.
(5) By Ryan Smith (cuz) on 2022-06-21 16:52:51 in reply to 3 [link] [source]
or store 1288 in the database and divide by 100 when you need the real (no pun intended) figure.
1288 / 100 will just yield 12.880000000001 again because IEE754. The only remedy is to format it to the precision that you need, if you care about precision.
(4) By Ryan Smith (cuz) on 2022-06-21 16:50:46 in reply to 1 [link] [source]
Stephen's very good reply already explains why this happens, I'll add a thought or two on how to deal with it.
While integers are easily precise as integers, floating point numbers are infinitely divisible and so we store any floating point number as the closest approximation to the target number. All computers using IEEE754 format floating point storage will do this.
In your example, 12.77 can be represented exactly, but 12.88 cannot, the very closest the computer IEEE754 can come to 12.88 is 12.880000000000001 at the limit of its fine-ness. Any bit added/subtracted to/from the least-significant bit will get a number further from the target 12.88 than 12.880000000000001.
You have to decide how many decimals are important to you (or your application) and then correct them by formatting the end-result. That said, please only format at the very end, after all calculations have been done, and only once showing the result to the user, because only humans care about neatness of numbers, the computer does not prefer 12.88 over 12.880000000000001 - those two numbers are exactly equal at the scale a computer can store values.
In FPC (Laz) formatting a value is easy, two ways that come to mind are (assuming str is a string and Num is the floating point number to display):
- str := FloatToStrF(Num, format, significant_digits, decimals)
- str := Format('Value = %0.3f', [Num])
The second one is more universal and equivalent to "Printf()" in C.
The first one allows very precise formatting and also doing it by variables (decimals and precision can be variables in a system that features user-adjustable precision numbers, for instance). The "format" specifier can be ffFixed, ffScientific, ffCurrency, or a bunch more, check the help for it.
(6) By Larry Brasfield (larrybr) on 2022-06-21 17:05:22 in reply to 4 [link] [source]
In your example, 12.77 can be represented exactly, but 12.88 cannot, ...
With usual floating point representation/hardware, the only numbers which can be represented exactly (as stored floating point values) are rational numbers whose denominator is an integer power of 2. The value, 12 + 77/100, is not such a number.
It is an accident of rounding1 for output formatting that the OP's obtained display of "12.77" for an FP value input as "12.77" happened to match.
The OP's question, regarding why this accident varies in occurrence, is not quite answered by the notion that, when it did happen, the input was susceptible to exact representation in binary floating point.
- ^ This is "accident" as in "not engineered". Of course, such results could be predicted with a sufficiently complex algoorithm.
(8) By Ryan Smith (cuz) on 2022-06-21 17:18:22 in reply to 6 [link] [source]
Quite correct - An error from trying to talk to the supplied example in stead of the ground truth, which is a mistake.
PS: I briefly considered fixing my post, but decided to leave it as is since these replies adequately serves to rectify it, and fixing it will render the replies obsolete.
(9) By HB9FIH on 2022-06-21 19:06:10 in reply to 8 [link] [source]
Many thanks to all for this logical and quite good explanations. So I know - I'm on the right way.
Its clear a float which is stored digital in a field must have an end and it ends with one bit.... For daily use within our applications doesn't matter.