Strange Float Screwup

Blitz3D Forums/Blitz3D Programming/Strange Float Screwup

Mortiis(Posted 2009) [#1]
Hi fellas, upon using this code I get a strange result which is beyond my knoweldge to explain.

Global a# = 0

For b = 0 To 125
	a=a+0.05
	Print a
Next

WaitKey()


Please try it, after some amount of increments, the float number of "a" gets a decimal like .0001, why would this happen? Any way to fix this? It's screwing a lightning system I'm working on.

Thanks.


GfK(Posted 2009) [#2]
Floating point inaccuracy - nothing you can do about it.

You should never ever depend on a float being equal to a specific value, because chances are it never will be.


Ross C(Posted 2009) [#3]
You can build your own floating point number system, using an a couple of integers, one for after the decimal point and one for before. You'll need to use types to store your numbers, to put the two ints in fields. Perform each calculation on both parts of the number, then add the results into one number. That way you can work with more decimal points more accuratly and return the floating point number back as normal.

TBH, it's probably more hassle than it's worth though :/


Who was John Galt?(Posted 2009) [#4]
Try calculating a by a multiplication each loop. It's probably no slower and should avoid the cumulative errors.


Mikel(Posted 2009) [#5]
Try this (I am not on my Blitz machine so I cannot test it)

Global a# = 0.00

For b = 0 To 125
a=a+0.05
Print a
Next

WaitKey()


Mortiis(Posted 2009) [#6]
Sadly it's the same Mikel, Can you give me the same example with multiplication John?

I wish there was a command to decrement the decimals a float has like converting 5.11 to 5.1


mtnhome3d(Posted 2009) [#7]
you could convert it to a string and remove the last character, them make it a float again


Stevie G(Posted 2009) [#8]
String manipulation is slow ..

See below ..

Global a1#, a2#

For b = 0 To 125
	a1 = a1 + .05
	a2 = ( b + 1 ) * .05 
	Print a1 + "   " + a2
Next

WaitKey()



Adam Novagen(Posted 2009) [#9]
Yeah, string stuff is likely to be slower. I've noticed these float errors before, and there really is nothing you can do about it. It's just a recurring math error. Mind you, Ross' double-integer method sounds promising... Plus it'll give you a greater number range, since normal floats only go to about 35,000...


GfK(Posted 2009) [#10]
you could convert it to a string and remove the last character, them make it a float again
That still isn't guaranteed to give an exact result. It might still end up as 5.09999999. And in any case, Blitzmax will still display it as "5.1000000" etc.


GIB3D(Posted 2009) [#11]
Awe, that explains why numbers go all wacky even though I could just simply be adding or subtracting .5 for something like a FPS game, or just to move around. Weird


Mortiis(Posted 2009) [#12]
Stevie that code looks rock solid accurate, even after 50.000 loops. But the real problem is the inaccuracy of the color interpolation code you gave me in the link. How would I fix the inaccuracy problems in this code?

http://www.blitzbasic.com/Community/posts.php?topic=82745


H. T. U.(Posted 2009) [#13]
I've been working at this for over an hour in Blitz3d, on a calculator, and even mentally as a final check. My brain is ready to explode, but the only errors I've noticed so far are miniscule (at least in the example). When "l" is less than 500, at least on my machine, the error is <= + or -.00001. How accurate does it need to be?


Stevie G(Posted 2009) [#14]
Simple, change DayNight to be an integer like so ..

While Not KeyDown(1)

	DayNight = ( DayNight + 1 ) Mod 400
	COLORinterpolate( DayNight / 100.0 , 64,255,64, 64,64,255, 255,64,64, 255,64,255 )

	AmbientLight aR, aG, aB
	RenderWorld()
	
	Text 0,0, ar + " "+ ag + " " + ab
	
	Flip

Wend



Mortiis(Posted 2009) [#15]
But that way I can't make it go any slower than +1 every frame and that is too fast for a realistic day-night cycle...


Stevie G(Posted 2009) [#16]
I've made some amendments. Pass your game 'Frames per second' and the number of seconds you want it to take to complete a full day night cycle in the DAYNIGHTinit function. Should be stable for an hour or so max. You probably don't want to be updating the colours every frame as your unlikely to see a difference.

Graphics3D 1024,768
SetBuffer BackBuffer()

Global camera = CreateCamera()

Global plane = CreatePlane()
RotateEntity plane, -90,0,0
PositionEntity plane, 0,0,5

Global DNcurrent, DNmod, DNdiv

DAYNIGHTinit( 50 , 120 )

While Not KeyDown(1)

	DAYNIGHTupdate()
	RenderWorld()
	
	Text 0,0, "Current: " + DNcurrent
	Text 0,10,"Mod    : " + DNmod
	Text 0,20,"Div    : " + DNdiv
	
	Flip

Wend

End

;====================================================================
;====================================================================
;====================================================================

Function DAYNIGHTinit( FPS , Time )

	Speed# = 4.0 / ( FPS * Time )
	DNmod = 4 / Speed
	DNdiv = 1 / Speed

End Function

;====================================================================
;====================================================================
;====================================================================

Function DAYNIGHTupdate()

	DNcurrent = ( DNcurrent + 1 ) Mod DNmod
	COLORinterpolate( DNcurrent / Float( DNdiv ) , 64,255,64, 64,64,255, 255,64,64, 255,64,255 )

End Function

;====================================================================
;====================================================================
;====================================================================

Function COLORinterpolate( t#, r1,g1,b1 , r2, g2, b2 , r3, g3, b3 , r4, g4, b4 )

	;get nearest integer below
	i = Floor( t )
	
	;get timestep 0 .. 1
	t = t - i

	Select i
		Case 0
			r = r1 + ( r2 - r1 ) * t
			g = g1 + ( g2 - g1 ) * t
			b = b1 + ( b2 - b1 ) * t
		Case 1
			r = r2 + ( r3 - r2 ) * t
			g = g2 + ( g3 - g2 ) * t
			b = b2 + ( b3 - b2 ) * t
		Case 2
			r = r3 + ( r4 - r3 ) * t
			g = g3 + ( g4 - g3 ) * t
			b = b3 + ( b4 - b3 ) * t
		Case 3
			r = r4 + ( r1 - r4 ) * t
			g = g4 + ( g1 - g4 ) * t
			b = b4 + ( b1 - b4 ) * t
	End Select
	
	AmbientLight r, g, b
	
End Function



Kryzon(Posted 2009) [#17]
And that's because you didn't get that strange floating value: "1.030-e103" something.
It's completely out of this world (a letter in the middle of a number?)


Wings(Posted 2009) [#18]
if you want to use double floats when change to blitz max or c+ :)


Mortiis(Posted 2009) [#19]
Any kind of number has that inaccuracy but integers Wings, I'll try that out Stevie, thanks a lot, you have been a great helper.