fslang-suggestions
fslang-suggestions copied to clipboard
Addition of a correct modulus operator
Addition of a correct modulus operator
The current remainder operator % can be surprising in that the sign of the result follows the sign of the dividend, so does not output periodic results for a fixed divisor.
Changing the current behavior of % has been declined in https://github.com/fsharp/fslang-suggestions/issues/417, so another way forward would be to add a new operator,
which, like a true modulus operator, would output positive results regardless of its inputs.
By always outputting positive results, we would achieve predictability and ease of use for periodic computations.
From F#'s OCaml roots, mod is keyword for an infix operator already, and is currently undefined in FSharp.Core:
let inline (mod) D d =
let r = D % d
if r >= LanguagePrimitives.GenericZero then r
elif d >= LanguagePrimitives.GenericZero then r + d
else r - d
// Usage: -5 mod 3
The existing way of approaching this problem in F# is to include such a definition everytime we use the operator, or bite ourselves when trying to use % on negative dividends.
Pros and Cons
The advantages of making this adjustment to F# are
- Raise awareness of the true modulus operator
- Less duplicated code across projects
- Assigning novel uses to existing available operators
The disadvantages of making this adjustment to F# are that the presence of both % and mod can be confusing. However, upon realisation that % stands for the remainder operation instead of modulus, and recognising the difference between the two operations, this can be solved.
Extra information
Estimated cost (XS, S, M, L, XL, XXL): XS
Related suggestions:
- https://github.com/fsharp/fslang-suggestions/issues/417
Affidavit (please submit!)
Please tick this by placing a cross in the box:
- [x] This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
- [x] I have searched both open and closed suggestions on this site and believe this is not a duplicate
- [x] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.
Please tick all that apply:
- [x] This is not a breaking change to the F# language design
- [x] I or my company would be willing to help implement and/or test this
For Readers
If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.
[...] a new operator, which, like a true modulus operator, would output positive results regardless of its inputs.
I think you should be more precise here. "The true modulus operator" returns a quotient group, not an integer (and certainly not a finite percussion int). In a congruence like
3 mod 2 \equiv 1
the symbol 1 does not represent the integer 1 but the set of all odd numbers. It would also be correct to replace it with 3, because it is also an odd number. Using the symbol 1 there instead of something else like 3 is merely convention because it is the canonical representation of the set of odd numbers.
Two uses for integer division (n div m, n mod m):
- Division with remainder. Here the conventional definition in mathematics, for m > 0, is n = mq + r, where 0 ≤ r <m.
- Finding quotient equivalence classes.
The definitions are intentionally compatible: the remainder found in the conventional definition, when applied to different n differing by a multiple of m, gives the same output.
In each case dotnet % is incorrect, for n < 0 and m > 0. E.g. -3 mod 2 should give 1 but gives -1. This contradicts the conventional definition in mathematics, since -1 < 0, and it also doesn't find a quotient equivalence class, since -3 mod 2 = 3 mod 2 evaluates to false instead of true.