how to get standard behavior of the Mod operator

BlitzMax Forums/BlitzMax Programming/how to get standard behavior of the Mod operator

Pineapple(Posted 2012) [#1]
BlitzMax's Mod operator is the equivalent of abs(x)%y. How can I just get x%y?


GfK(Posted 2012) [#2]
I don't follow. Are you saying that you want this code:
Print -16 Mod 10
...to give this result
-6
....?

Because that's what it does, here.


Pineapple(Posted 2012) [#3]
no. It *does* give -6, I want it to give 4.

this can be accomplished by doing ((x mod y)+y) mod y, but that seems horribly inefficient when it should be able to be done with only one expression.

Last edited 2012


TomToad(Posted 2012) [#4]
http://en.wikipedia.org/wiki/Modulo_operation This will explain the differences in various computer languages when using modulus on negative numbers. C, C++, C#, Pascal, and most BASIC derivatives behave the same way that BlitzMAX does.

http://en.wikipedia.org/wiki/Modular_arithmetic shows the various ways in which modulus can be viewed and how it affects negative numbers.

Maybe someone can create an efficient mod function that actually returns 4 instead of -6, then you can choose which version you want to use depending on application.


Floyd(Posted 2012) [#5]
There is no standard behavior, only whatever the programming language uses.

X Mod Y in BlitzMax is like X % Y in many other languages. In BlitzMax the result has the same sign as X. C++ and Java do the same. Python gives the same sign as Y. None of them always gives a non-negative result.

Since the behavior you want is not built into BlitzMax you will have to do it yourself.

It's true this won't be as efficient as the current X Mod Y. But I don't think there is any way around that. Intel's assembly language uses the same convention, i.e. result has the sign of X. So any implementation of Mod would first have to do things the way they are now and then adjust the result if it is negative.

Last edited 2012


Yasha(Posted 2012) [#6]
that seems horribly inefficient


Given that the operators in question are usually implemented as hardware instructions, that's about as efficient as you're going to get.


TomToad(Posted 2012) [#7]
Ok, after messing around a bit, I've come up with 3 equations, each with it's own advantages.



consider the equation r = n mod d, if n = -15 and d = 8...

Blitzmax Mod function returns -7, standard in many programming languages. The other versions return 1, which is what MadK's formula returns, as well as a few other languages (such as Excel).

All equations are slower than the built in function except for Toad3 which requires that d be positive and a power of 2. Toad2 and toad3 will only work on integers (or longs by replacing the number 31 with 63 in the equations). BlitzMAX will not compile them if you use floats. Toad1 probably is the most useless. It is slower than MadK's when using floats or doubles. It is faster than MadK's when using int or long, but not as fast as toad2.

Any of them could be the best depending on your application. If you want the result that blitzmax returns, or if you know you will not be using negative numbers, then just use the mod function; unless you know that d will be both positive and a power of 2, then use the toad3 function. If you want the results that MadK is expecting, and you are using float or double, then use MadK's version. If you are using int or long, then use toad2 version.

So, can any of you improve on that?

Last edited 2012


Nate the Great(Posted 2012) [#8]
for toad1 and toad2 I get

4151
Result Toad1 Mod= 1

4142
Result Toad2 Mod= 1


it seems they are pretty much the same, but maybe it depends on the processor? I think this would make toad1 superior if you are dealing with floats though considering none of the others work with floats.

Last edited 2012


TomToad(Posted 2012) [#9]
What I get for MadK, Toad1, and Toad2 when using Ints are
24621
Result MadK Mod = 1

18224
Result Toad1 Mod= 1

17310
Result Toad2 Mod= 1


But when I change n, d, and r to floats and rem out toad2 and toad3, I get
19008
Result MadK Mod = 1.00000000

28178
Result Toad1 Mod= 1.00000000


As you can see, Toad1 is worse than MadK when using floats, so might as well use MadK version. When using ints, even though Toad1 and toad2 are close, toad2 wins by a few cycles.
I also wonder just how accurate Toad1 would be on floats, vs MadK's function. Since it uses comparisons, you might not get the intended result if n or d are very close to zero.


Nate the Great(Posted 2012) [#10]
Delay(2000)
Time = MilliSecs()
For x = 1 To iter
	r = n
	If r<0 Then
		r = n+d
	EndIf
Next

Print MilliSecs() - time
Print "Result Nate's Mod= "+r+"~n"


I added this one and it runs *exactly* as fast as toad3 down to the millisecond with ints but its only useful if you are subracting small enough amounts from a number that it would never go negative furthur than the d value, so for this example you have to change n to -7 and d to 8, this is useful to know for anything like ship rotation in a game, where the ship will hopefully never be rotating -360 degrees in one rotation. It should be noted that this is probably what everyone does already, so its nothing special! At least we can test that this simple solution for a problem with more specific parameters than the original is much faster.

Last edited 2012


Pineapple(Posted 2012) [#11]
I hadn't realized the behavior I was looking for wasn't the standard, thank you much the lot of you for the interest and the code ^^