www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - mod of negative number

reply Craig Dillabaugh <craig.dillabaugh gmail.com> writes:
Why does the following program:

     \<code>
         import std.stdio;

         int main(string[] args) {
             uint Q = 7681;
             writeln("Val = ", -1 % Q);
             return 0;
         }
     \</code>

     Print
         Val = 5568


Was hoping for 1.

I assume it is an integer promotion issue, but I am unsure how to 
resolve.  I tried replacing the Q with to!int(Q) but this gave me 
-1, which is closer but not right either.
Sep 23
next sibling parent reply Craig Dillabaugh <craig.dillabaugh gmail.com> writes:
On Monday, 23 September 2024 at 19:52:02 UTC, Craig Dillabaugh 
wrote:
 Why does the following program:

     \<code>
         import std.stdio;

         int main(string[] args) {
             uint Q = 7681;
             writeln("Val = ", -1 % Q);
             return 0;
         }
     \</code>

     Print
         Val = 5568


 Was hoping for 1.

 I assume it is an integer promotion issue, but I am unsure how 
 to resolve.  I tried replacing the Q with to!int(Q) but this 
 gave me -1, which is closer but not right either.
Opps, sorry. I was expecting 7680 (not -1 or 5568).
Sep 23
parent Craig Dillabaugh <craig.dillabaugh gmail.com> writes:
On Monday, 23 September 2024 at 20:02:25 UTC, Craig Dillabaugh 
wrote:
 On Monday, 23 September 2024 at 19:52:02 UTC, Craig Dillabaugh 
 wrote:
 Why does the following program:
snip
 Opps, sorry.  I was expecting 7680 (not -1 or 5568).
After a bit of research I see this is the same behavior as C, so I guess that explains the result.
Sep 23
prev sibling next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, September 23, 2024 1:52:02 PM MDT Craig Dillabaugh via Digitalmars-
d-learn wrote:
 Why does the following program:

      \<code>
          import std.stdio;

          int main(string[] args) {
              uint Q = 7681;
              writeln("Val = ", -1 % Q);
              return 0;
          }
      \</code>

      Print
          Val = 5568


 Was hoping for 1.

 I assume it is an integer promotion issue, but I am unsure how to
 resolve.  I tried replacing the Q with to!int(Q) but this gave me
 -1, which is closer but not right either.
Well, this is what the spec says: https://dlang.org/spec/expression.html#division - Jonathan M Davis
Sep 23
prev sibling next sibling parent Sergey <kornburn yandex.ru> writes:
On Monday, 23 September 2024 at 19:52:02 UTC, Craig Dillabaugh 
wrote:
 Why does the following program:

     \<code>
         import std.stdio;

         int main(string[] args) {
             uint Q = 7681;
             writeln("Val = ", -1 % Q);
             return 0;
         }
     \</code>

     Print
         Val = 5568


 Was hoping for 1.

 I assume it is an integer promotion issue, but I am unsure how 
 to resolve.  I tried replacing the Q with to!int(Q) but this 
 gave me -1, which is closer but not right either.
Check section "In Programming languages" - https://en.wikipedia.org/wiki/Modulo There are different operations (remainder and modulus) and operators (modulo) which could be combined in a different ways
Sep 24
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 9/23/24 21:52, Craig Dillabaugh wrote:
 Why does the following program:
 
      \<code>
          import std.stdio;
 
          int main(string[] args) {
              uint Q = 7681;
              writeln("Val = ", -1 % Q);
              return 0;
          }
      \</code>
 
      Print
          Val = 5568
 
 
 Was hoping for 1.
 
 I assume it is an integer promotion issue, but I am unsure how to 
 resolve.  I tried replacing the Q with to!int(Q) but this gave me -1, 
 which is closer but not right either.
Yes, what this does is to promote `-1` to `uint.max` and the result you are getting is `uint.max % 7686`. `-1 % 7686` does not work because division rounds towards zero, so the result of modulo may be negative. In general `a%b` will give you a value between `-abs(b)+1` and `abs(b)-1`, matching the sign of `a` (and ignoring the sign of `b`). You can use something like `auto r=a%b; if(r<0) r+=abs(b);` or `auto r=(a%b+b)%b;`, depending an your needs (note that those two are not the same for negative `b`, but they match for positive `b`). This implementation is equivalent to `(a%b+b)%b`, if you want to avoid the second modulo and the compiler is not smart enough: ```d int floormod(int a,int b){ bool sign=(a<0)^(b<0); auto r=a%b; if(sign&&r!=0) r+=b; return r; } ``` The interpretation of this is to compute the remainder for a division that rounds to negative infinity. Sometimes one might also want `a%0 = a`, but this is a special case that has to be checked as the language will give you a division by zero error.
Sep 24