Цель состоит в следующем:
(a + b) / 2 = ((a ^ b) >> 1) + (a & b)
И примените его ко всем четырем байтам целого числа.Если бы это был всего один байт, то сдвиг вправо на 1 бит отбросил бы самый правый бит.Однако в этом случае самый правый бит из первых 3 байтов не отбрасывается - он сдвигается в соседний байт.Следует помнить, что вам нужна маска последнего бита каждого байта, чтобы она не «загрязняла» соседний байт во время сдвига.Например, скажем, что a ^ b это:
a XOR b = 1011 1101 1110 1001
Сдвиг вправо на 1 бит без маски будетвыглядеть так:
(a XOR b) >> 1 = 0101 1110 1111 0100
Что не так.Нулевая маска выводит последний бит каждого байта, чтобы этого не произошло:
(a XOR b) И 0xfefefefe = 1010 1100 1110 1000
ТогдаВы можете безопасно сдвинуть это значение вправо:
((a XOR b) И 0xfefefefe) = 0101 0110 0111 0100
Итак:
#define AVERAGE(a, b) ( ((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)) )
Следует иметь в виду, что C не отличает арифметическое смещение вправо от логического смещения вправо с помощью своего оператора.Вы должны убедиться, что целочисленные значения, которые вы смещаете, являются беззнаковыми, чтобы предотвращали специфичное для реализации смещение целых чисел со знаком voodoo .
EDIT : я думаю, что @dasblinkenlight, возможно, избил меня этим ответом.Просто остерегайтесь сдвигать целые числа со знаком, и вы должны быть хорошими.