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