Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 12:45 30 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : lesson in floating point

Author Message
crez

Senior Member

Joined: 24/10/2012
Location: Australia
Posts: 152
Posted: 11:50pm 10 Oct 2013
Copy link to clipboard 
Print this post

try this short program in mmbasic:

a=0 : b=10 : c=100 : d=1000 : e=10000

For k=1 To 10000
a=a+0.0001
b=b+0.0001
c=c+0.0001
d=d+0.0001
e=e+0.0001
Next k

b=b-10 : c=c-100 : d=d-1000 : e=e-10000

Print "a";a,"b";b,"c";c,"d";d,"e";e

The results are interesting.

David
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3659
Posted: 12:20am 11 Oct 2013
Copy link to clipboard 
Print this post

In what way(s)?

John
 
crez

Senior Member

Joined: 24/10/2012
Location: Australia
Posts: 152
Posted: 01:10am 11 Oct 2013
Copy link to clipboard 
Print this post

John,
In a 'perfect' world, you would expect all the results to be 10000 * 0.0001, which is 1. The program above gives errors that are both positive and negative, and the error is worst when adding a small increment (0.0001) to a large number (10000). In this case it seems the sum of 10000 increments of 0.0001 is 0

This is the result of the above program:
a 1.00005
b 1.00136
c 0.991821
d 1.2207
e 0

I expect that a careful examination of the floating point precision being used would explain the results.

David
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3659
Posted: 05:06am 11 Oct 2013
Copy link to clipboard 
Print this post

We've discussed this on this forum before. It's an inherent (i.e. unavoidable) feature of computer fp (floating point). It affects x86 PCs, Macs, mainframes etc etc.

If you don't want it, don't use fp! (It's why COBOL, for example, has BCD.)

The underlying cause is that the range of fp is large and there are many values it cannot precisely represent i.e. there are quantisation effects.

You can get a similar effect using an old-fashioned calculator if you divide a number (that's not a multiple of 3) by 3 or 9 etc then later multiply by 3 (or 9).

JohnEdited by JohnS 2013-10-12
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5906
Posted: 10:35am 11 Oct 2013
Copy link to clipboard 
Print this post

32 bit floating point maths has about 7 significant digits. In your example, 'e' is trying for 10 significant digits.

Floating point maths is always a shock when you first see its limitations.
Page 15 of the help file:
  Quote  Numbers are stored and manipulated as single precision floating point numbers. The maximum number that
can be represented is 3.40282347e+38 and the minimum is 1.17549435e-38
The range of integers (whole numbers) that can be manipulated without loss of accuracy is ±16777100.


Double precision numbers would be nice but they would come with big overheads. There are external chips that will do double precision if needed and I did produce a program for doing big integer maths (but very slow).

Jim
VK7JH
MMedit   MMBasic Help
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 11:17am 11 Oct 2013
Copy link to clipboard 
Print this post

I would like 32 bit integers. High precision and very fast.
Of course you need both floating point and integers to cover programming needs.

Microblocks. Build with logic.
 
crez

Senior Member

Joined: 24/10/2012
Location: Australia
Posts: 152
Posted: 11:48am 11 Oct 2013
Copy link to clipboard 
Print this post

I'm not complaining or suggesting there is something that needs fixing. I was caught by this and other part-time programmers like me might be caught too. In my case I was adding small energy measurements ( eg 0.001 watt-hours ) every 50 milliseconds to a daily total that was reaching 9000. It was fine at the start of the day, but by the end of the day it failed completely. One fix would be to have a second energy total that is emptied into the main one when it reaches a significant level, or every ten seconds, which would reduce the problem by two orders of magnitude.

David
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 02:55pm 11 Oct 2013
Copy link to clipboard 
Print this post

Maybe you could multiply each small value by 1000 before adding it to the total, then divided the total by 1000 at the end. That would bring you back into the 7 decimal place range of accuracy for the additions.

James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
crez

Senior Member

Joined: 24/10/2012
Location: Australia
Posts: 152
Posted: 02:29am 12 Oct 2013
Copy link to clipboard 
Print this post

James,
The problem arises from the difference in magnitude between the sum and the increment. It is not the actual size of the numbers but the huge difference in size.
Multiplying each small value by 1000 would increase the sum by a factor of 1000, so we would be back to square 1.
I have added a second variable to hold a temporary sum. When this reaches 1 I empty it into the original sum. In this way, even when the samples get quite small, I am not adding a variable to one that is more than 10000 times its size, so the errors will be insignificant.

David
 
isochronic
Guru

Joined: 21/01/2012
Location: Australia
Posts: 689
Posted: 05:35pm 23 Oct 2013
Copy link to clipboard 
Print this post

I did a quick look around, it looks like Arduinos and their offshoots do the same thing (apart from the chipKit based version), maybe someone could verify that. It is a bit of a stretch in scope for the smaller platforms to go to 64 bit math I guess.
 
Gizmo

Admin Group

Joined: 05/06/2004
Location: Australia
Posts: 5017
Posted: 06:54pm 23 Oct 2013
Copy link to clipboard 
Print this post

This reminds me of a discussion I had with a work mate. He was writing a game in C++ as a learning exercise, on a 32bit platform, and discovered a problem when he wanted to track the milliseconds the player had been playing. If the player was playing for too long, the counter would reset and start again, reaching the integer limit on a 32bit byte. His solution was to move to a 64 bit system!

After some discussion and my reassuring him the first PC's only used 8 bits, but could still process large numbers, he changed his code to break up the number into 2 32bit bytes. Problem solved.

In Crez's application, I would record the watt hours for one hour, then reset it back to zero for the next hour. At the end of the day, add all 24 hour totals to get the watt hours for the day.

Glenn

The best time to plant a tree was twenty years ago, the second best time is right now.
JAQ
 
isochronic
Guru

Joined: 21/01/2012
Location: Australia
Posts: 689
Posted: 05:07am 29 Oct 2013
Copy link to clipboard 
Print this post

As it happens, I am almost finished a small fortran-ish interpreter
for pic32mx that has double precision datatypes and so on.
It is (deliberately) whimsical in that number-crunching with an interpreter
tends to be a complete contradiction !! However... I thought
I would run an approximation of the example above, out of curiosity.
It looks ok, the double precision gives you about 12 significant figures,
it is a little slow on a mx1 but a '795 should be nice.
Now I need a 64-bit analog-to-digital converter


PRINT "Hello world" ;
INTEGER*4 a;
DOUBLE b, c, d, e, f, g ;
b = 0.00000000000 ;
c = 10.00000000000 ;
d = 100.00000000000 ;
e = 1000.00000000000 ;
f = 10000.00000000000 ;
g = 0.00010000000 ;
DO 10 a = 1,10000 ;
b = b + g ;
c = c + g ;
d = d + g ;
e = e + g ;
10 f = f + g ;
PRINT "b = ", b ;
PRINT "c = ", c ;
PRINT "d = ", d ;
PRINT "e = ", e ;
PRINT "f = ", f ;
PRINT "Finished" ;
END;
\
Hello world
b = 1.0000000
c = 11.0000000
d = 101.0000000
e = 1001.0000000
f = 10001.0000000
Finished
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024