Why do such operations:
std::cout << (-7 % 3) << std::endl;
std::cout << (7 % -3) << std::endl;
give different results?
-1
1
Why do such operations:
std::cout << (-7 % 3) << std::endl;
std::cout << (7 % -3) << std::endl;
give different results?
-1
1
From ISO14882:2011(e) 5.6-4:
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded; if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a.
The rest is basic math:
(-7 / 3) => -2
-2 * 3 => -6
so a % b => -1
(7 / -3) => -2
-2 * -3 => 6
so a % b => 1
Note that
If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.
from ISO14882:2003(e) is no longer present in ISO14882:2011(e)
%
in the case of negative arguments. –
Liberalism a % b
in c++ default:
(-7 / 3) => -2
-2 * 3 => -6
so a % b => -1
(7 / -3) => -2
-2 * -3 => 6
so a % b => 1
in python:
-7 % 3 => 2
7 % -3 => -2
in c++ to python:
(b + (a % b)) % b
The sign in such cases (i.e when one or both operands are negative) is implementation-defined. The spec says in §5.6/4 (C++03),
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.
That is all the language has to say, as far as C++03 is concerned.
-7/3
would result in -3
, but that would be in a very distant past.) –
Keeley b
is a power of 2, it used to be possible to compute n % b
as n & (b-1)
. The new standard requires that it be computed as n < 0 ? n | -b : n & (b-1)
. Likewise, n / b
cannot be written as a simple shift, even on hardware that supports arithmetic shifts; instead, on such systems, an expression like n/16
(if n
is an int32
) must be written as n < 0 ? (n+15) >> 4 : n >> 4
. Horrible standard, IMHO. Note that since non-power-of-two division is inherently slow anyway, mandating Euclidian behavior wouldn't have slowed it down much. –
Rainie n / 16
should be written as n / 16
. Say what you mean. The newly mandated behavior is the behavior people expect (whether it is right or wrong), and the behavior of all existing hardware. –
Keeley foo /= 16
could be written as asr [dword foo],4
. Under the new rules, the optimal representation requires many more instructions [perhaps mov eax,[foo] / mov ebx,eax, asr eax,31 / lsr eax,28 / add eax,ebx / asr eax,4 / mov [foo],eax
] Not as slow as a divide instruction, but a lot more work than a simple shift. –
Rainie int x = -7, y = 4; string.Format("{0} ÷ {1} = {2}{3}", x, y, x/y, (x%y==0) ? "" : string.Format(" {0}/{1}", Math.Abs(x%y), Math.Abs(y)));
That handles every possible value of x and y in 2 lines of code. However, I don't see how this is really relevant since trying to do this with Euclidean division, you would end up with "-7 ÷ 4 = -2 1/4" and trying to fix it would be much more complicated. –
Countryside © 2022 - 2024 — McMap. All rights reserved.
-7/3
results in-2
or-3
). – Keeley