Float precision

Previous topic - Next topic

Minion

Have a very weird bug here.

Code (glbasic) Select
LOCAL mx%=0
LOCAL manx=9.0
LOCAL c=0

REPEAT
manx=manx+0.2
mx=manx
PRINT mx+"   "+manx,0,c
c=c+16

UNTIL mx>15
SHOWSCREEN
KEYWAIT


and heres the results ...

Code (glbasic) Select
9   9.2
9   9.4
9   9.6
9   9.8
9   10
10   10.2
10   10.4
10   10.6
10   10.8
10   11
11   11.2
11   11.4
11   11.6
11   11.8
11   12
12   12.2
12   12.4
12   12.6
12   12.8
12   13
13   13.2
13   13.4
13   13.6
13   13.8
13   14
14   14.2
14   14.4
14   14.6
14   14.8
14   15
15   15.2
15   15.4
15   15.6
15   15.8
15   16
16   16.2


notice that when manx is a whole number and i assign it to the int, it doesnt register it as such ;(

MrTAToad

#1
Its more of a display oddity than floating precision.  For example, when it displays 10, it's actually 9.9999999999999999999993552713679

For best results, you should use FORMAT$ and take the integer value from that, thus :

Code (glbasic) Select
LOCAL mx%=0
LOCAL manx=9.0
LOCAL c=0
LOCAL temp$

REPEAT
manx=manx+0.2
temp$=FORMAT$(5,2,manx)
mx=INTEGER(temp$)
PRINT mx+"   "+temp$,0,c
c=c+16

UNTIL mx>15
SHOWSCREEN
KEYWAIT


[edit]
10.0 is internally 9.99999999999xxx not 9.00000000000xx ;)

Minion

Thanks for the infor, but sadly thats not a viable option. Strings are very slow and using hundreds of them will slow down my program no end ;(


Kitty Hello

If you work with floats, never ever rely on 1+1=2.
Always have an epsilon (tiny noise value) for comparisons:

IF ABS(a-b) < 0.000001 THEN

instead of
IF a = b THEN


bigsofty

#4
You could push it over the edge, dunno if that's a viable way to do it though...  :S

Code (glbasic) Select
mx=manx+0.000000000001

Edit: number was too small, so I changed it, doh!
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Slydog

What a pain this is, but not much we can do about it.

Well, you could try:
Code (glbasic) Select
LOCAL manx=9.000000000001 // or however many '0' are allowed

I hate how floats can round down below the integer version of its value.
Too bad we couldn't force them to always round up a bit  (or down if negative).
Ah, the nature of floats!
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Minion

Its a bit of a bugger. Im going to have to scrap floats from my interpreter now ;(

fivesprites

or...

IMPORT "C" double round(double)

mx = round(manx)

manx = 9.2, mx = 9
manx = 9.4, mx = 9
manx = 9.6, mx = 10
manx = 9.8, mx = 10
manx = 10, mx = 10
manx = 10.2, mx = 10
manx = 10.4, mx = 10
manx = 10.6, mx = 11


Slydog

You can always keep your 'floats' in integer form, if you want a certain precision.
If you only need one decimal place, multiply by 10, 2 decimals, multiply by 100, etc.

Then convert them when you need to display them (or in other calculations):

Code (glbasic) Select
LOCAL manx%=90  // Really 9.0 - This 'float' is stored as an integer x 10
LOCAL c=0

REPEAT
manx=manx+2  // Really + 0.2
PRINT INTEGER(manx/10)+"   "+manx/10,0,c
c=c+16
UNTIL manx>150
SHOWSCREEN
KEYWAIT
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

spacefractal

Not a bug, it's depend what value was present in a binary form before calculated:

http://blogs.office.com/b/microsoft-excel/archive/2008/04/10/understanding-floating-point-precision-aka-why-does-excel-give-me-seemingly-wrong-answers.aspx

Hence would been nice as a round command directly from float to int (same as format does, but directly). Small thing.
Genius.Greedy Mouse - Karma Miwa - Spot Race - CatchOut - PowerUp Elevation - The beagle Jam - Cave Heroes 2023 - https://spacefractal.itch.io/

Minion

(mainly for gernot)...what routine are you using in order to display the float ? If I print a float it says 10.2, but if i compare it to 10.2 it does nothing. If i could use the same routine that is used when printing that would fix my problem.

fivesprites

Or, if this is what you're after:

manx = 9, mx = 9
manx = 9.2, mx = 9
manx = 9.4, mx = 9
manx = 9.6, mx = 9
manx = 9.8, mx = 9
manx = 10, mx = 10
manx = 10.2, mx = 10
manx = 10.4, mx = 10
manx = 10.6, mx = 10

then you can get it with:

IMPORT "C" double ceil(double)

mx = ceil(manx*100)/100.0



Moru

#12
Or the classical:

Code (glbasic) Select
mx=manx+0.05

If I understand you correctly that you want mx to be the integer of manx? No need to import c functions for this.

Oh, and if you are just debugging numbers you can use the "DEBUG" command to just type it out in the debug-window so you don't have to bother with positioning text on the screen.

Code (glbasic) Select
DEBUG "\n mx="+mx+" manx="+manx

Minion

Problem solved. Ive given myself 5 decimal places precision in my floats, and now there is no trouble comparing things like 10.2 (it didnt work before, id print the value and it would say 10.2, but if i did a compare it didnt accept it) all works fine now. Im happy.

MrTAToad

Could always use fixed point maths :)