Perl
print 2 % -18;
- >
-16
Tcl
puts [expr {2 % -18}]
- >
-16
но VBScript
wscript.echo 2 mod -18
- >
2
Почему разница?
Perl
print 2 % -18;
- >
-16
Tcl
puts [expr {2 % -18}]
- >
-16
но VBScript
wscript.echo 2 mod -18
- >
2
Почему разница?
ответ на wikipedia здесь весьма полезен.
Краткий обзор состоит в том, что любое целое число можно определить как
a = qn + r
где все эти буквы являются целыми числами, а
0 <= | r | < | П |.
Для почти каждого языка программирования потребуется (a/n) * n + (a% n) = a. Поэтому определение модуля почти всегда будет зависеть от определения целочисленного деления. Существует два варианта для целочисленного деления на отрицательные числа 2/-18 = 0 или 2/-18 = -1. В зависимости от того, какой из них подходит для вашего языка, обычно изменяется оператор%.
Это связано с тем, что 2 = (-1) * -18 + (-16) и 2 = 0 * -18 + 2.
Для Perl ситуация сложная. На странице руководства говорится: "Обратите внимание, что когда use integer находится в области видимости," % "дает вам прямой доступ к оператору модуля, реализованному вашим C компилятор. Этот оператор не так хорошо определен для отрицательных операндов, но он будет выполняться быстрее". Таким образом, он может выбрать любой вариант для Perl (например, C), если использовать integer в области видимости. Если целое число используется не в объеме, в руководстве говорится: "Если значение $b отрицательно, то $a% $b равно $a минус наименьший кратный $b, который не меньше $a (т.е. результат будет меньше или равен равным нулю).
Википедия "Modulo operation" страница объясняет это довольно хорошо. Я не буду пытаться делать здесь лучше, так как я, вероятно, сделаю тонкую, но важную ошибку.
В результате этого вы можете определить "остаток" или "модуль" по-разному, а разные языки выбрали различные варианты реализации.
После деления числа и делителя, один из которых отрицателен, у вас есть как минимум два способа разделить их на частное и остаток, так что фактор-делитель + остаток = число: вы можете либо округлить частное отрицательной бесконечности или к нулю.
Многие языки просто выбирают один.
Я не могу устоять, указав, что Общий Lisp предлагает оба.
python, конечно, явно сообщает вам
>>> divmod(2,-18)
(-1, -16)