Кажется, существует общая путаница между терминами "по модулю" и "остаток".
В математике остаток * всегда должен определяться в соответствии с частным, так что если a / b == c rem d
, то (c * b) + d == a
. В зависимости от того, как вы округлите частное, вы получите разные остатки.
Однако по модулю всегда должен получаться результат 0 <= r < divisor
, который согласуется только с делением от округления до минус бесконечности, если вы разрешите отрицательные целые числа. Если деление округляется до нуля (что является общим), то по модулю и остатку эквивалентны только для неотрицательных значений.
Некоторые языки (особенно C и C ++) не определяют требуемые поведения округления / остатка, и %
является неоднозначным. Многие определяют округление до нуля, но используют термин по модулю, где остаток будет более правильным. Python относительно необычен тем, что округляется до отрицательной бесконечности, поэтому по модулю и остатку эквивалентны.
Ада округляет до нуля IIRC, но имеет операторов mod
и rem
.
Политика C предназначена для того, чтобы компиляторы могли выбирать наиболее эффективную реализацию для машины, но IMO - это ложная оптимизация, по крайней мере, в наши дни. Хороший компилятор, вероятно, сможет использовать эквивалентность для оптимизации везде, где отрицательное число не может появиться (и почти наверняка, если вы используете неподписанные типы). С другой стороны, там, где могут встречаться отрицательные числа, вы почти наверняка заботитесь о деталях - по причинам переносимости вы должны использовать очень тщательно разработанные сверхсложные алгоритмы и / или проверки, чтобы гарантировать, что вы получите желаемые результаты независимо от округления и остатка поведение.
Другими словами, выгода для этой «оптимизации» в основном (если не всегда) иллюзия, тогда как в некоторых случаях это очень реальные затраты - так что это ложная оптимизация.