Problem with Mod command

BlitzMax Forums/BlitzMax Beginners Area/Problem with Mod command

Fry Crayola(Posted 2005) [#1]
This is confusing me a bit.

Try the code:

print 2^(7-0)


And you should get a value of 128.00000 (and so forth)


But if you try
b:Int = 0 Mod 8

Print 2^(7-b)


You get 127.99999997.

Why are these results different, and how can I get around it?


Tiger(Posted 2005) [#2]
Hello, I got 127.99999997 every time, with or without the mod line.


Dreamora(Posted 2005) [#3]
this is because the ^ command.
with variables it seems do something different than with constant


FlameDuck(Posted 2005) [#4]
Why are these results different, and how can I get around it?
They aren't really different. The problem here is that IEEE Floating point aritmetic is attempting to fit an infinite series of numbers into a finite ammount of space (in this case 80 or 64 bits). Ofcourse this is impossible to do with absolute accuracy (if you can figure out otherwise you might just get a nobel prize).

As for a "way around it" use integer (CPU) instructions (^ is an FPU instruction) or rethink the algorithm. In your case this would be
Print 1 Shl (7-0)
b:Int = 0
Print 1 Shl (7-b) 



Dreamora(Posted 2005) [#5]
The problem is a different one:

According to official (think they were official) comments, ^ s implementation differs from compile to runtime.
This means if you only use constants, it is compiled in a different way than if you do it with variables ... and it seems like the later version is quite instable. But I think this might be "repaired" with BM 1.11


FlameDuck(Posted 2005) [#6]
This means if you only use constants, it is compiled in a different way than if you do it with variables
This holds true for everything though. Any expression using only constants (and thus by extension, also being a constant), is replaced (at compile time) by its value, as there is no need to do expensive operations when the result is already known. Pretty run-of-the-mill compiler optimization.


Fry Crayola(Posted 2005) [#7]
Ah, fair enough. My workaround was to use Ceil() around the value to round it up, once I finally found the right command I was looking for.

FlameDuck's suggestion is just as good though. Or is it better?

I'll have to run a test on it to find out the faster command.


Dreamora(Posted 2005) [#8]
FlameDuck: this might be, but this is no usefull explanation why the runtime implementation should be different from compiler time implementation, especially as ^ is significantly slower than doing loop "*" ing the stuff if you have an int power.

If it would have at least some use for speed it perhaps could be "accepted"


MrCredo(Posted 2005) [#9]
i think ^ ist a double-type-operator - the same like pow()


FlameDuck(Posted 2005) [#10]
Or is it better?
It's better - as long as you only need 2^some integer value, as a logical shift left (as it's called) is a single in-line CPU instruction. No FPU setup overhead, no conversion overhead and no invokation overhead.

but this is no usefull explanation why the runtime implementation should be different from compiler time implementation,
Well for starters the FPU could be in a different state at compile time vs. runtime.


Dreamora(Posted 2005) [#11]
ok 2^x is something special at least for ints ... but I wouldn't even touch it for that and straight use shl / shr (as for color-int splitting and bit-mask stuff in 1-hot encoding)