Thread overview
mod of negative number
Sep 24
Sergey
September 23

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.

September 23

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).

September 23

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.

September 23
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



September 24

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

September 24
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.