4

I found the following behavior surprising:

int a = -2;
int b = 5;
uint c = 5;
std::cout << a%b << '\n';
std::cout << a%c << '\n';

Output:
-2
4

When comparisons are involved, mixing signed and unsigned is problematic - is there a hidden comparison in the operator %, or is there something else taking place here?

stafusa
  • 195
  • 1
  • 15
  • Note that a%b could also be 3. It is implementation defined weather % on negative numbers has a positive or negative result. – Goswin von Brederlow Jul 10 '18 at 10:15
  • @GoswinvonBrederlow Not since C++11. – stafusa Jul 10 '18 at 10:16
  • @GoswinvonBrederlow See https://stackoverflow.com/a/12711070/1264299 – stafusa Jul 10 '18 at 10:22
  • That link doesn't mention weather / must round towards 0 or down. The quoted C++11 part only say `(a/b)*b + a%b is equal to a`. It at least used to be that a / b would round differently on different CPUs and the standard allowed that. The % then changes to preserve the mentioned equality. – Goswin von Brederlow Jul 10 '18 at 10:31
  • @GoswinvonBrederlow When it says "*For integral operands the / operator yields the algebraic quotient with any fractional part discarded*", I understand it to mean that a truncation is done - therefore, "rounding" to zero. – stafusa Jul 10 '18 at 11:44

1 Answers1

6

Assuming that uint is an unsigned type no narrower than int, in the evaluation of the expression a % c, a is converted to uint and it will have the value -2 + std::numeric_limits<uint>::max() + 1.

For a 32 bit uint, that number is 4294967294, which modulo 5 is 4.

For a 16 bit uint, that number is 65534, which modulo 5 is, again, 4.

Reference: https://en.cppreference.com/w/c/language/conversion

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Thanks. Ok, so there's no comparison, but `%` triggers the same conversion. Can you indicate a place where that's documented? – stafusa Jul 10 '18 at 08:47
  • @stafusa: I've added a reference that virtually proxies the standard. – Bathsheba Jul 10 '18 at 08:48
  • Ah, ok - I had searched for "modulus" and then missed that: "The arguments of the following arithmetic operators undergo implicit conversions for the purpose of obtaining the common real type, which is the type in which the calculation is performed: binary arithmetic *, /, %, +, - " – stafusa Jul 10 '18 at 08:50
  • @stafusa: Exactly! Do feel free to cobble all this together and answer your own question. I'd upvote it. – Bathsheba Jul 10 '18 at 08:50