Spin modulo operator broken?
DrGary
Posts: 7
Is the modulo operator in Spin broken? It produces (arguably) incorrect results for negative numbers.
For example, I expect -5 // 24 to return 19 as it does in Ruby/Python. Instead, it returns -5.
There are actually a variety of definitions for modulo operations in various languages with respect to negative dividends. See this wikipedia entry for a list. It seems that the Spin // behavior has been carried over from Fortran, but some modern languages have adopted a definition more mathematically consistent. See this discussion.
BTW, the Propeller manual calls it a "modulus" operator. That's at variance with common CS/engineering usage of "modulo." Given the confusion surrounding the definition of the operator, perhaps "remainder" would be the most appropriate name.
Why do I expect -5 // 24 to return 19? It's simple. If it's 1am now, then 6 hours ago it was (1-6)//24 = 19 hours or 7pm. As another example, suppose you're doing week calculations with days numbered from Sunday=0. You expect that if today is Monday (1), then 3 days ago would be a Friday(5). (1-3)//7=5. But Spin returns -2. Yuk.
A work-around is to add the modulo divisor if the dividend is negative:
For example, I expect -5 // 24 to return 19 as it does in Ruby/Python. Instead, it returns -5.
There are actually a variety of definitions for modulo operations in various languages with respect to negative dividends. See this wikipedia entry for a list. It seems that the Spin // behavior has been carried over from Fortran, but some modern languages have adopted a definition more mathematically consistent. See this discussion.
BTW, the Propeller manual calls it a "modulus" operator. That's at variance with common CS/engineering usage of "modulo." Given the confusion surrounding the definition of the operator, perhaps "remainder" would be the most appropriate name.
Why do I expect -5 // 24 to return 19? It's simple. If it's 1am now, then 6 hours ago it was (1-6)//24 = 19 hours or 7pm. As another example, suppose you're doing week calculations with days numbered from Sunday=0. You expect that if today is Monday (1), then 3 days ago would be a Friday(5). (1-3)//7=5. But Spin returns -2. Yuk.
A work-around is to add the modulo divisor if the dividend is negative:
'' return x // y, assuming rounding toward -infinity, instead of the rounding toward 0 assumed by the current implementation of Spin PRI remainder(x,y) if x < 0 return (x // y) + y return x // y
Comments
I've seen industrial motion controllers do this, where if the position encoder spins backwards from zero, the position goes negative up to the max count (now the minimum count) of the encoder.
After any sort of offset math (turn the valve on 50 degrees from this position), I had to be sure to call the correction function. Personally I called it "PositionModulus( )". Again it acted equivalent to your function.
As annoying as this was for you, it isn't an uncommon thing for mod to do that.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.