.NET Forum / Languages / C# / September 2007
Using Remainder Operator with Negative Divident
|
|
Thread rating:  |
valentin tihomirov - 23 Sep 2007 22:22 GMT My rateonale is: -1 mod 3 = must be 3 0 mod 3 = 0 1 mod 3 = 1 2 mod 3 = 2 3 mod 3 = 3 4 mod 3 = 0 = 1 = 2 = 3 = 0
We note a sequence: 0 1 2 3 0 1 2 3 0 1 2 3. Going in backward direction, we get 3 2 1 0 3 2 1 0 3 2 1 0.
Since (0 % N) is 0, going one step back (-1 % N) must result in N. But c# compiler gives me -1. It is wrong. Fix it. The C#LS seems wrong. Correct it.
Jon Skeet [C# MVP] - 23 Sep 2007 22:53 GMT > My rateonale is: > -1 mod 3 = must be 3 [quoted text clipped - 13 lines] > Since (0 % N) is 0, going one step back (-1 % N) must result in N. But c# > compiler gives me -1. It is wrong. Fix it. The C#LS seems wrong. Correct it. Your understanding of "remainder" is too rigid. Fix it :)
Seriously, there are different understandings of how remainders should work with negative numbers. Some systems use the sign of the dividend, others use the sign of the divisor. See http://en.wikipedia.org/wiki/Modulo_operation for a list.
You know what I think is *really* broken? To leave it to the implementation - which is what C++ did, at least at the time of Stroustrup's 2nd edition. (I seriously hope it's been fixed since then.)
(I have in my head that "remainder" should work as shown in C#, but if a language defines a "modulo" operator, that should always be non- negative. However, I can't find any evidence backing that up.)
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Doug Semler - 23 Sep 2007 23:15 GMT > (I have in my head that "remainder" should work as shown in C#, but if > a language defines a "modulo" operator, that should always be non- > negative. However, I can't find any evidence backing that up.) What should be non-negative? The result of the modulus operator? If the dividend is negative in C#, the result of the modulus is negative, which actually makes sense mathematically (what would you need to ADD to the result of the divisor times the result of the division to get back to your dividend?) Note this is only for integer modulus. I always hated float modulus :)
-3 / -2 = 1 - what would you need to add? (-1) so -3 % -2 = -1 -3 / 2 = -1 - what do you add? -1 again. so -3 % 2 = -1 3 / -2 = -1 - what do you need to add to -1 * -2?
 Signature Doug Semler, MCPD a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh). The answer is 42; DNRC o- Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?
Doug Semler - 23 Sep 2007 23:22 GMT >> (I have in my head that "remainder" should work as shown in C#, but if >> a language defines a "modulo" operator, that should always be non- [quoted text clipped - 6 lines] > dividend?) Note this is only for integer modulus. I always hated float > modulus :) Note that my note above was for the example below, not that float modulus acted differently with respect to sign <g>
> -3 / -2 = 1 - what would you need to add? (-1) so -3 % -2 = -1 > -3 / 2 = -1 - what do you add? -1 again. so -3 % 2 = -1 > 3 / -2 = -1 - what do you need to add to -1 * -2?
 Signature Doug Semler, MCPD a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh). The answer is 42; DNRC o- Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?
Jon Skeet [C# MVP] - 24 Sep 2007 00:08 GMT > > (I have in my head that "remainder" should work as shown in C#, but if > > a language defines a "modulo" operator, that should always be non- > > negative. However, I can't find any evidence backing that up.) > > What should be non-negative? The result of the modulus operator? Yes - in my head, anyway :)
> If the dividend is negative in C#, the result of the modulus is negative, which > actually makes sense mathematically (what would you need to ADD to the > result of the divisor times the result of the division to get back to your > dividend?) Note this is only for integer modulus. I always hated float > modulus :) Yes, I totally see your point. Of course, it depends on how you round the division aspect. If you define integer division to round down, i.e. to always return the largest number d such that d*x < y, then you will always have a non-negative integer r such that d*x+r = y. However, C# (and many other computer languages) use round-towards-zero for division, which is where the negative remainder comes in.
At least, that's what I currently think - but I'm about to go to bed, so anything I write now probably shouldn't be trusted.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
valentin tihomirov - 24 Sep 2007 08:24 GMT > Your understanding of "remainder" is too rigid. Fix it :)
:) You do not understand. THIS IS REQUIREMENT OF MY PROGRAM! This math is required for Rayal Mail http://emce.gov.uk/documents/publications/royal_mail/4)%20Royal%20Mail%20Cleanma il%20Brochure.pdf checksum character computation. They map chars (0 1 2 3 4 5 ...) to increments (1 2 3 4 5 0) by (i + 1) % 6. Afterwards, the sum is divided by 6 and the index (0 1 2 3 4 5 ...) must be reporduced from the reminder (1 2 3 4 5 0 ...). In order for the math to work, the reverse operation (sum - 1) % 6 must treat the last column 0 as 6 resulting in char 5.
Jon Skeet [C# MVP] - 24 Sep 2007 08:37 GMT > > Your understanding of "remainder" is too rigid. Fix it :) > > :) You do not understand. THIS IS REQUIREMENT OF MY PROGRAM! So write a method to behave how you want it to, rather than trying to force the rest of us to change.
The following probably isn't the cleanest way of doing it, but it's incredibly simple (assuming a positive divisor - when the divisor is negative, I don't know what you'd want to do).
public static int Modulus (int dividend, int divisor) { int remainder = dividend % divisor; return remainder >= 0 ? remainder : remainder+divisor; }
> This math is required for Rayal Mail > http://emce.gov.uk/documents/publications/royal_mail/4)%20Royal%20Mai... [quoted text clipped - 3 lines] > 4 5 0 ...). In order for the math to work, the reverse operation (sum - 1) % > 6 must treat the last column 0 as 6 resulting in char 5. So you expect a language to change to support a single use case which doesn't seem terribly well thought out? I'm afraid I have very little sympathy for that position. Work round it - it's trivial to do so.
Jon
valentin tihomirov - 24 Sep 2007 09:27 GMT >> > Your understanding of "remainder" is too rigid. Fix it :) >> [quoted text clipped - 29 lines] > > Jon Actually, I have determined that their algorithm can be implemented without wrapping the last column to 0 forth and back, which require these ugly if-else. It is the Royal Mail User Guide, which must be fixed then (simplified).
Jon Skeet [C# MVP] - 24 Sep 2007 10:01 GMT > Actually, I have determined that their algorithm can be implemented without > wrapping the last column to 0 forth and back, which require these ugly > if-else. It is the Royal Mail User Guide, which must be fixed then > (simplified). I'd prefer their algorithm to be fixed - keep the content of the table where it is, but make 0 the first row/column. Too late to do that now, but clearly you can remap the table if you're willing to change where the contents are. It's only a lookup, after all.
Jon
valentin tihomirov - 24 Sep 2007 10:21 GMT > I'd prefer their algorithm to be fixed - keep the content of the table > where it is, but make 0 the first row/column. Too late to do that now, > but clearly you can remap the table if you're willing to change where > the contents are. It's only a lookup, after all. The algorithm seems correctly designed. The explanation is bad moving the 0 column into the end and back for no reason.
Jon Skeet [C# MVP] - 24 Sep 2007 10:23 GMT > > I'd prefer their algorithm to be fixed - keep the content of the table > > where it is, but make 0 the first row/column. Too late to do that now, [quoted text clipped - 3 lines] > The algorithm seems correctly designed. The explanation is bad moving the 0 > column into the end and back for no reason. Yes, by "algorithm" I guess I really meant "data used by the algorithm" - i.e. the table.
Either way, it's certainly not C#'s fault :)
Jon
james.curran@gmail.com - 24 Sep 2007 16:11 GMT > You know what I think is *really* broken? To leave it to the > implementation - which is what C++ did, at least at the time of > Stroustrup's 2nd edition. (I seriously hope it's been fixed since > then.) I doubt it. Especially considering the C++ standard still does not require a particular binary representation for -1, or, for that matter, a particular value for 32767+1.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|