siiky
2023/06/17
2023/06/17
en
Alright, you know what's coming you smart cookies. This is a rant.
Before going further, if you're a programmer, try to remember whether % is the remainder or the modulo in the programming languages you know (obviously, only the ones that use %). No cheating! Don't check online or try it in a REPL before answering mentally!
I'll list these later: C, D, Go, JS, Lua, Python, Rust, Zig, Java.
There are two related, though different, operations on integers called "remainder" and "modulo". The "remainder" should need no introductions, it's the remainder of integer division. The "modulo" may be more "obscure" but is somewhat similar.
For natural numbers (N), the remainder is the same as the modulo. That is, when both dividend and divisor are positive, the result is equal. Here are some examples in CHICKEN.
#;1> (remainder 4 2) 0 #;2> (modulo 4 2) 0 #;3> (remainder 4 3) 1 #;4> (modulo 4 3) 1 #;5> (remainder 5 3) 2 #;6> (modulo 5 3) 2
However, when the dividend is a non-natural integer (Z\N, i.e. negative), the result may differ:
#;7> (remainder -4 2) 0 #;8> (modulo -4 2) 0 #;9> (remainder -4 3) -1 #;10> (modulo -4 3) 2 #;11> (remainder -5 3) -2 #;12> (modulo -5 3) 1
That should be enough to convince you that remainder and modulo are different.
If you want to learn more about modular arithmetic, you can read an older post of mine:
Unbeknownst to me, some people use remainder/modulo almost interchangeably online: they call the remainder "remainder". Or sometimes "modulo" -- you can choose whichever you prefer. :) *similing but crying screaming inside*
Given the above, when you read "remainder" online you can be pretty sure it is "remainder" the writer meant. But when you read "modulo" you have to take a look outside: what's the current phase of the moon?
Unfortunately, when one is looking for or reading documentation, one is not much in the mood to go outside, or in fact doesn't have the time -- one needs to know NOW is it the remainder or the modulo quick QuiCk QUICK!
While researching to write this I found the following blog post.
Mod and Remainder Are Not The Same
"Thank you!" I thought after reading the title. Then it starts:
Get ready, here comes some fringe pedantry (...)
"It's neither fringe nor pedantry!" I thought now. And it continues:
Anyway: last week I found out something weird that I thought I would share: mod and remainder are not the same thing.
(...)
I had to look this up too, just like the last time the subject came up. It's one of those things that I know, but don't retain.
"Oh no, just another person who doesn't know what the modulo is... :/"
I also found these two Wikipedia pages refering to the % operator as the "modulo operator".
gemini://gemi.dev/cgi-bin/wp.cgi/view/en?Modulo
gemini://gemi.dev/cgi-bin/wp.cgi/view/en?C_(programming_language)#Operators
Fuck me...
| C | remainder | | D | remainder(?) | | Go | remainder | | JS | remainder | | Lua | modulo | | Python | modulo | | Rust | remainder | | Zig | remainder |
C17 § 6.5.5 Multiplicative operators; point 5
D Language Reference § 10.15 Mull Expressions
The Go Programming Language Specification § Arithmetic operators
MDN JavaScript Reference § Remainder (%)
Lua 5.4 Reference Manual § 3.4.1 Arithmetic Operators
The Python Language Reference § 6.7 Binary arithmetic operations
The Rust Reference § Arithmetic and Logical Binary Operators
Zig Language Reference § Table of Operators
Of these, D is the one I'm not sure about. Some parts of the docs say "remainder" others "modulo". It's probably remainder.
Lua and Python seem to compute the modulo indeed (no extensive testing, a single example should be enough assuming a well-working implementation).
The Java Tutorials § The Arithmetic Operators
There're two more very important questions left for me.
How did I come to believe that the % operator in C/C++, Go, Java, and Rust was the modulo? I started studying/using C 8~9 years ago. How was I wrong about this so very important detail for so long?
And how was I never bit by this so very important detail until yesterday?!
To answer the first, I guess the most likely cause is the "modulo is just another word remainder" ill together with never having been bit by it.
To answer the second, my best guess is that C, Go, and Rust all have unsigned numbers, unlike some other languages (fucking Jaba). JS, Lua, and Python don't have unsigned integers either (or integers at all <_<) but I don't use them much.
I have no idea... The modulo seems to be the most useful operation of the two. That's good enough reason for % to be the modulo for me, but I'll leave these data points.
A colleague sent this ChatGPT reply, but I wouldn't trust it for anything:
The reason why most programming languages chose to implement the % operator as a remainder operation rather than a modulo operation is largely historical and related to the way that division is typically implemented at the hardware level. In many hardware architectures, division is defined in such a way that it rounds towards zero, which naturally leads to a remainder operation when used with the % operator.
In #chicken@libera.chat:
<Bunny351> what is decisive is probably what the CPU does (e.g. "idiv") as low level languages will use whatever the CPU does by default
In #c@libera.chat:
<supakeen> From what I recall it had to do with the implementation being allowed to pick what to do in the case `/` (round to -inf or round to 0)
<supakeen> So % automatically became its brother.
<supakeen> This was also defined at some point.
<supakeen> It likely has to do with / and % working together.
<siiky> so it's just an historical implementation detail?
<supakeen> No, it's that remainder plus integer division work well together.
If you can take out of this post a single little thing, let it be this: REMAINDER IS NOT MODULO!
And please share the word!