Proposal: New operator %% for canonical Modulus operations #4744
Replies: 77 comments 34 replies
-
I like the idea of a true modulo operator. I'm not sure |
Beta Was this translation helpful? Give feedback.
-
The title of this proposal doesn't make any sense. The entire point of the modulo operation is to get the remainder that is produced from long-dividing two numbers, so there is no such thing as "true modulo" that isn't obtaining that remainder.
According to Wikipedia, there is no rigid mathematical specification of how modulo should work with negative numbers.
|
Beta Was this translation helpful? Give feedback.
-
Let me be specific then: I want a Modulus operator which returns between 0 (incl) and divisor (excl). Also, Microsoft's own definition of the |
Beta Was this translation helpful? Give feedback.
-
Then call |
Beta Was this translation helpful? Give feedback.
-
And you want this operation for what exactly? What is this is the mathematical meaning of this operation? What code is |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr That does not do what I want, at all. The output value should loop around the bounds. As I've already stated the work-around is to add the second value if the result is negative. But this is not trivial (well, not as trivial as an operator), and there are compiler optimizations only possible with a true Modulus operation. |
Beta Was this translation helpful? Give feedback.
-
Example use case: Let's say you divide a coordinate system into pieces of 100. If you are at position 5, you are at subposition 5 of piece 0. If you are at 230, you are at subposition 30 of piece 2. If you are at position -20, you are at subposition 80 of piece -1. The reason you're not at subposition -20 or 20 is because the subpositions should always be positive AND increasing when position is increasing. If we were at subposition -20 of piece 0 then piece 0 would be two times as large as any other piece. I am sure there are many, many more uses for Modulus, but this is what I have in mind. |
Beta Was this translation helpful? Give feedback.
-
Are there really so many uses do justify adding a new operator? What's wrong with adding a |
Beta Was this translation helpful? Give feedback.
-
Of course that's up for debate, but I would argue that a new operator is a good idea. I would also support adding a |
Beta Was this translation helpful? Give feedback.
-
I changed the title to better reflect the issue, but technically it's wrong.
I couldn't fit all this into a short title, but hopefully it gets the point across. |
Beta Was this translation helpful? Give feedback.
-
It probably makes more sense to do what Java does - add |
Beta Was this translation helpful? Give feedback.
-
@aaronfranke I'm afraid the terminology you're using doesn't seem to be ideal. If people search the term ‘modulus,’ they'll discover that it's a synonym for ‘absolute value.’ Also, specifically, you're looking for the Euclidean variant of the modulo operation. (Or possibly the floored division variant? Can't tell.) C# already has the truncated division variant. |
Beta Was this translation helpful? Give feedback.
-
It turns out Eric Lippert blogged about this exact thing back in 2011. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 I want what Eric Lippert calls "Canonical Modulus". I don't care if Modulus has conflicting definitions in the mathematical world (nobody in programming calls absolute value as "modulus"). I just want a math operator. |
Beta Was this translation helpful? Give feedback.
-
Can you not just provide that operator in a library? Why does hte language need first class support for it? |
Beta Was this translation helpful? Give feedback.
-
Actually, % used to mean "divide by 100". Many programming languages use it, however, for the remainder operation and very few for modulus. |
Beta Was this translation helpful? Give feedback.
-
@quinmars % is not ÷ EDIT: Sorry, completely missed the "by 100" part. |
Beta Was this translation helpful? Give feedback.
-
@aaronfranke, correct. % is the "per cent" sign. |
Beta Was this translation helpful? Give feedback.
-
I think @aaronfranke and @kshetline have both articulated the issues with the existing implementation of
|
Beta Was this translation helpful? Give feedback.
-
Regardless of the argument around whether Adding new features to the language is not "trivial" and comes with a cost. Generally proposals start at An easy way to show proof that this is worth the cost is to start by adding the functionality to the core libraries. This will require someone to open an API proposal (https://github.com/dotnet/runtime/issues/new?assignees=&labels=api-suggestion&template=02_api_proposal.md) at which point it will get tagged as This, or even a 3rd party library, would allow telemetry to be gathered on "how many users actually need this" and if it gets enough usage that can be used as an argument for why the language should directly support it as well. |
Beta Was this translation helpful? Give feedback.
-
To me it seems like this should be added as a method like But yes, I definitely think we need an |
Beta Was this translation helpful? Give feedback.
-
% operator is inherited from C. C's % operator is also remainder, because it is the natural side effect of the division operation in the CPU. Maybe C# should have been ground breaking and fixed this in version 1.0. But then again, enums. Still a Modulo function would be nice. |
Beta Was this translation helpful? Give feedback.
-
Also I want to second the idea that just because other languages aren't doing something doesn't mean C# shouldn't. C# has the |
Beta Was this translation helpful? Give feedback.
-
+1 to this As a developer who's done graphics programming in GLSL and is now porting some LED strip animation code from Python, it's really quite frustrating that not only does my maths no longer work (and hey, % being different is what it is, that ship has sailed) but there's no replacement on-hand. C++ also appears to define % like C#, but at least it brings along std::fmod and std::remainder (ironically, fmod does what C# calls remainder, and remainder does what is being asked for here). There's a whole bundle of maths that just breaks halfway down the number line when modulo ("remainder") is defined like this, and there's still no standard alternative. For every other lost soul who ends up in this thread: |
Beta Was this translation helpful? Give feedback.
-
I've opened an API proposal for this functionality here: dotnet/runtime#65408 All feedback is welcome. |
Beta Was this translation helpful? Give feedback.
-
Bump. I still strongly believe this should be a thing. I continue to believe that:
See also the discussion in dotnet/runtime#65408 which proposes a method - but I think this should be an operator. |
Beta Was this translation helpful? Give feedback.
-
I'll champion this. |
Beta Was this translation helpful? Give feedback.
-
Once there were a %% operator, delinters could flag % for replacement by %%, just as they now flag == for replacement by ===, as the current % functionality is seldom what people really want.
…
Having "only the wrong operator" (%) in the language is not good.
The proposed operator (%%) is purposefully similar to % to help with readability and discoverability.
|
Beta Was this translation helpful? Give feedback.
-
I don't want to steer the discussion and I know this topic was discussed multiple times but something like infix functions would have been great addition to the language for Math and DSLs then asks for specific operators might have been less common. Sometimes you just want to work with a cleaner syntax like |
Beta Was this translation helpful? Give feedback.
-
This use is really common, considering that issue had to be moved to discussion, and many comments this discussion got. This issue discussed not only here, but it multiple stackoverflow questions, and other forums. It spans multiple areas, as specified in the first post (angles, dates, etc). This feature is being discussed for more than a decade. Each comment against it meets multiple comments for it. Now for a personal story. In the past few years, I had the same bug due to unexpected behaviour of % operator. I keep coming to this page, remembering the whole conversation here, and writing the same function over and over again. I visited this page at least 3 times (that I remember of), and had to write the same function many more times. I can not comprehend why it is still not added. |
Beta Was this translation helpful? Give feedback.
-
Note: The title may be slightly confusing without a definition of canonical Modulus. The idea is for
a %% b
to be on the range[0, b)
, soa %% 3
would be on the range[0, 3)
, anda %% -3
would be on the range[0, -3)
. As usual, the pattern holds that asa
increases, so does the output. The behavior is identical to%
when both numbers are positive.Currently, C# has the operator
%
for the Remainder operation. This is different from the canonical Modulus when it comes to negative numbers (like the%
operator in Python). For example,-5 % 8
is-5
with the Remainder operation but it is3
with the Modulus operation (proposed syntax:-5 %% 8
returns3
).Modulus always returns between 0 (inclusive) and the second argument (exclusive). Yes, this means that it should keep the sign of the second argument.
a %% 8
is on range [0, 8)By contrast, Remainder can return between the negative second argument (exclusive) and the second argument (again, exclusive).
a % 8
is on range (-8, 8)With
a % b
the current behavior is like this:What should ideally be a consistent pattern is broken at 0, so it isn't very useful if you need both positive and negative numbers.
With
a %% b
the proposed behavior would be like this:Currently, I implement Modulus on top of Remainder in my program like this:
A new operator,
%%
, would serve the following purposes:Easily allow the writing of true canonical Modulus operations, rather than Remainder operations. I can imagine more use cases for this.
As @quinmars noted, the compiler itself performs optimizations to change
%
to bitwise when it is passeduint
types. Therefore, the compiler could also improve the performance of the%%
true Modulus operation, when givenint
types rather thanuint
(int
is much more common thanuint
), and the second argument is a power-of-two, by making it bitwise.Make developers aware of the issue and endorse the correct usage. To quote @vladd:
A few use cases from the replies below:
Indexes in arrays, tables, bucket hash tables, circular buffers, and ring buffers.
Finding sub-positions in a grid coordinate system.
Working with angles.
Working with dates and times.
Beta Was this translation helpful? Give feedback.
All reactions