Возможный дубликат:
C ++ оператор% гарантирует
В С ++ 98/03
5.6-4
Двоичный / оператор дает частное, а двоичный оператор%
дает остаток от деления первого выражения на
второй. Если второй операнд / или% равен нулю, поведение
не определено; в противном случае (a / b) * b + a% b равно a. Если оба операнда
неотрицательны, то остаток неотрицателен; если нет, знак
остаток определяется реализацией.
В с ++ 11:
5,6 -4
Двоичный / оператор дает частное, а двоичный оператор%
дает остаток от деления первого выражения на
второй. Если второй операнд / или% равен нулю, поведение
не определено. Для интегральных операндов оператор / дает алгебраический
частное с любой дробной частью отбрасывается; 81, если частное a / b
представляемый в типе результата, (a / b) * b + a% b равен a.
Как вы можете видеть, что определенный для реализации бит знака отсутствует, что с ним происходит?
Поведение %
был ужесточен в C ++ 11 и теперь полностью указан (кроме деления на 0
).
Сочетание усечения до нуля и идентичности (a/b)*b + a%b == a
подразумевает, что a%b
всегда позитивно для позитива a
и отрицательный для отрицательного a
,
Математическая причина этого заключается в следующем:
Позволять ÷
быть математическим делением, и /
быть C ++ подразделением.
Для любых а и б имеем a÷b = a/b + f
(где f — дробная часть), и из стандарта мы также имеем (a/b)*b + a%b == a
,
a/b
Известно, что усечь 0
поэтому мы знаем, что дробная часть всегда будет положительной, если a÷b
положительный, а отрицательный a÷b
отрицательно:
sign(f) == sign(a)*sign(b)
a÷b = a/b + f
можно переставить, чтобы дать a/b = a÷b - f
, a
может быть расширен как (a÷b)*b
:
(a/b)*b + a%b == a
=> (a÷b - f)*b+a%b == (a÷b)*b
,
Теперь левая сторона также может быть расширена:
(a÷b)*b - f*b + a%b == (a÷b)*b
a%b == f*b
Напомним, что ранее sign(f)==sign(a)*sign(b)
, так:
sign(a%b) == sign(f*b) == sign(a)*sign(b)*sign(b) == sign(a)
Алгоритм говорит (a/b)*b + a%b = a
, который легче читать, если вы помните, что это truncate(a/b)*b + a%b = a
Используя алгебру, a%b = a - truncate(a/b)*b
, То есть f(a,b) = a - truncate(a/b)*b
, Для каких ценностей f(a,b) < 0
?
Не имеет значения, если b
отрицательный или положительный. Это отменяет себя, потому что это появляется в числителе и знаменателе. Даже если truncate(a/b) = 0
а также b
отрицательно, ну, это будет отменено, когда это продукт 0
,
Поэтому это только знак a
который определяет знак f(a,b)
, или же a%b
,