Hacker News new | past | comments | ask | show | jobs | submit login

This article focusses on the (rather uninteresting) case of taking the modulus/remainder of some positive dividend divided by a negative divisor.

However, the real distinction lies in how the two operations handle negative dividends: If n is positive, the modulo operator

  x mod n
always returns a number between 0 and n – 1. The remainder operator returns a number between –n + 1 and 0 if x is negative instead. For example,

  -17 mod 12 = 7
and

  -17 rem 12 = -5.
I have yet to see a case where the remainder operator is the one that you want. If a language only supports rem I find myself constantly writing

  (x rem n + n) rem n
(which is just

  x mod n).



For this reason, Zig requires the programmer to specify which is intended when the operator is used on signed integers:

  var x: i32 = -17 % 12; //compile error: remainder division with '(integer literal)' and '(integer literal)': signed integers and floats must use @rem or @mod
  var y: i32 = @mod(-17, 12); //7
  var z: i32 = @rem(-17, 12); //-5


> (x rem n + n) rem n

Correct me if I'm wrong, but this is also attractive because it can be applied even to an "actual modulo" operator. That is, because "(x mod n + n) mod n" has the same behavior as the above, one need not even know which way a particular language's "%" operator behaves if one just always uses this filter.


a = b ( mod n) is defined as n | a - b That is n is a divisor of a -b ( a, b, n integers n non zero) Obviously if p is prime and p | n Then also a = b ( mod p)


I know. But programming languages usually don’t have the modulo relation but a modulo operator that sends each number to a special representative of its equivalence class. For positive numbers, everyone agrees that this should be the smallest nonnegative number (i.e. the representative between 0 and n – 1). However, there are two conventions for the representative of a negative number: Some programming languages return the largest nonpositive number (the article calls this the remainder), others return the smallest nonnegative number in this case as well (the article calls this the modulus). I chose to write mod and rem instead of % to be able to make this distinction.


I recalling seeing these referred to as modp (positive) and mods (symmetric) back in University. This seems to be the clearest way to distinguish them. I didn't realize different popular programming languages used different versions for the % operator...

The case of a negative denominator doesn't seem to make sense when talking about modulo in an algebraic sense. I don't think you can have a Ring with a negative dimension. So I've never even thought about what % would do with a negative denominator (RHS). If I was using % with an unknown denominator as input, I could just as easily end up with it being 0 which would be a bad thing, so I think it's fair to say I always require it to be positive.


No, the symmetric version is yet a third variant. What people are calling “rem” is what you get with division that rounds toward zero, whereas what they are calling “mod” is what you get with division that always rounds down. A symmetric version is what you get with division that rounds to the nearest integer, and I have not seen any language with a built-in operator for it.

To the grandparent:

> sends each number to a special representative of its equivalence class

The problem is that many programming languages have a “remainder” type % operator which does not do this in the case where the dividend is negative. For instance,

    -1 % 3 == -1
    2 % 3 == 2
Instead, folks who want mathematically reasonable behavior need to implement their own. For instance in Javascript we can define

    mod = (a, b) => a - b*Math.floor(a/b)


Grandparent here: I know, that’s what I tried to explain (poorly) with the next sentences. Programming languages with a remainder operator choose two representatives for every equivalence class except [0] and return the one that has the same sign as the dividend.

I tend to define

  mod = (a, b) => (a % b + b) % b
because it works without going through floats – in languages that have integer types. I don’t know if there are actual advantages though.


Well, algebraically, Z/nZ and Z/(–n)Z are the same. However, you have again some choice of canonical representative (and you might choose differently for n and –n). But I agree that this is a rather rare case.


I don't think there is a formal universal distinction in programming between a "modulo operator" and a "remainder operator" in terms of behaviour. Wikipedia says that the result of a modulo operation varies between languages [0]. Furthermore, by mathematical convention as seen in the Euclidean division theorem, the remainder is always in [0, n).

[0]: https://en.wikipedia.org/wiki/Modulo_operation#Remainder_cal...




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: