Strange Float Screwup

Blitz3D Forums/Blitz3D Programming/Strange Float Screwup

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.

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.

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 :/

Try calculating a by a multiplication each loop. It's probably no slower and should avoid the cumulative errors.

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()

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

you could convert it to a string and remove the last character, them make it a float again

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()


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...

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.

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

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

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?

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


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...

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


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?)

if you want to use double floats when change to blitz max or c+ :)

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.