kemiisto писал(а):
...Вот
ещё на аглицком о том же.
В этой статье есть два интересных фрагмента:
Здесь говорится о том, что при компиляции выражения
x MOD
y (где
y — константа) компилятор может применить простую оптимизацию в случае, если делитель есть степень двойки. Это простая оптимизация, наподобие свёртывания констант. В компиляторах Вирта всегда реализованы такие оптимизации. Оптимизация состоит в следующем. Вместо того, чтобы выдавать машинный код деления, выдаётся код поразрядной операции И на величину, на единицу меньшую, чем делитель:
x AND (
y - 1). Оптимизация срабатывает и в том случае, если делимое отрицательно.
Однако, если в языке программирования операции деления с остатком определены так, что остаток от деления имеет знак делимого (как в стандарте Си с 1999 года и почти во всех языках), таковая оптимизация оказывается невозможной.
Цитата:
Compiler optimizations may recognize expressions of the form expression % constant where constant is a power of two and automatically implement them as expression & (constant-1), allowing the programmer to write clearer code without compromising performance. This simple optimization is not possible for languages in which the result of the modulo operation has the sign of the dividend (including C), unless the dividend is of an unsigned integer type. This is because, if the dividend is negative, the modulo will be negative, whereas expression & (constant-1) will always be positive.
Это показывает, почему язык Оберон определяет остаток от деления как всегда неотрицательный (и меньший делимого).
В другом месте этой статьи говорится о следующем. Если остаток от деления определён так, что он имеет знак делимого, то выражение (
n MOD 2 = 1) отражает чётность числа лишь для неотрицательных значений n. Если же
n — отрицательное нечётное число, остаток будет равен -1. В Обероне же остаток всегда неотрицателен.
Цитата:
When the result of a modulo operation has the sign of the dividend (truncated definition), it can lead to surprising mistakes.
For example, to test if an integer is odd, one might be inclined to test if the remainder by 2 is equal to 1:
Код:
bool is_odd(int n) {
return n % 2 == 1;
}
But in a language where modulo has the sign of the dividend, that is incorrect, because when n (the dividend) is negative and odd, n mod 2 returns −1, and the function returns false.