int getMax(int a, int b) {
int c = a - b;
int k = (c >> 31) & 0x1;
int max = a - k * c;
return max;
}
Давайте розберемо це. Цей перший рядок здається прямим - він зберігає різницю a
та b
. Це значення є негативним, якщо a < b
і в іншому випадку невід’ємним. Тут насправді є помилка - якщо різниця чисел a
і b
така велика, що не може поміститися в ціле число, це призведе до невизначеної поведінки - ой! Тож припустимо, що тут цього не відбувається.
У наступному рядку, який є
int k = (c >> 31) & 0x1;
ідея полягає в тому, щоб перевірити, чи значення c
від’ємне. Практично на всіх сучасних комп'ютерах числа зберігаються у форматі, який називається доповненням двох, в якому найвищий біт числа дорівнює 0, якщо число додатне, і 1, якщо число від'ємне. Більше того, більшість ints мають 32 біти. (c >> 31)
зміщує число на 31 біт, залишаючи найвищий біт числа на місці для найнижчого біта. Наступний крок, коли беремо це число та додаємо до нього 1 (двійкове представлення якого дорівнює 0 скрізь, крім останнього біта), стирає всі старші біти і просто дає вам найнижчий біт. Оскільки найнижчий біт c >> 31
- це найвищий біт c
, це читає найвищий біт c
як 0 або 1. Оскільки найвищий біт дорівнює 1, якщо c
дорівнює 1, це спосіб перевірити, чиc
є негативним (1) або позитивним (0). Поєднуючи це міркування з вищезазначеним, k
це 1, якщо a < b
і 0, інакше.
Останній крок - це зробити:
int max = a - k * c;
Якщо a < b
, тоді k == 1
і k * c = c = a - b
, і так
a - k * c = a - (a - b) = a - a + b = b
Що є правильним максимумом, оскільки a < b
. В іншому випадку, якщо a >= b
, то k == 0
і
a - k * c = a - 0 = a
Що також є правильним макс.
<
.