У вас вже є розумна відповідь: непідписана арифметика - це модульна арифметика, і, отже, результати будуть тримати, ви можете це математично довести ...
Однак одна крута річ щодо комп’ютерів полягає в тому, що комп’ютери працюють швидко. Дійсно, вони настільки швидкі, що перерахування всіх дійсних комбінацій із 32 бітів можливо за розумний проміжок часу (не намагайтеся використовувати 64 біти).
Отже, у вашому випадку мені особисто подобається просто кидати його в комп’ютер; мені потрібно менше часу, щоб переконати себе, що програма правильна, ніж потрібно, щоб переконати себе, ніж математичний доказ правильний і що я не контролював деталі в специфікації 1 :
#include <iostream>
#include <limits>
int main() {
std::uint64_t const MAX = std::uint64_t(1) << 32;
for (std::uint64_t i = 0; i < MAX; ++i) {
for (std::uint64_t j = 0; j < MAX; ++j) {
std::uint32_t const a = static_cast<std::uint32_t>(i);
std::uint32_t const b = static_cast<std::uint32_t>(j);
auto const champion = (a + (b & 255)) & 255;
auto const challenger = (a + b) & 255;
if (champion == challenger) { continue; }
std::cout << "a: " << a << ", b: " << b << ", champion: " << champion << ", challenger: " << challenger << "\n";
return 1;
}
}
std::cout << "Equality holds\n";
return 0;
}
Це перераховує всі можливі значення a
і b
в 32-біт простору і перевіряє , чи правильно рівність, чи ні. Якщо це не так, друкується корпус, який не працював, що можна використовувати як перевірку стану здоров’я.
І, думку Кланга : Рівність має місце .
Крім того, враховуючи, що арифметичні правила є агностичними по ширині бітів (вище int
бітової ширини), ця рівність буде виконуватися для будь-якого цілого беззнакового типу, що становить 32 біти або більше, включаючи 64 біти і 128 бітів.
Примітка: Як компілятор може перерахувати всі 64-бітові шаблони в розумні часові рамки? Це не може. Петлі були оптимізовані. Інакше ми всі загинули б до припинення страти.
Спочатку я довів це лише для 16-бітових цілих чисел без знака; на жаль, C ++ - це божевільна мова, де int
спочатку перетворюються малі цілі числа (менші бітові ширини ніж )int
.
#include <iostream>
int main() {
unsigned const MAX = 65536;
for (unsigned i = 0; i < MAX; ++i) {
for (unsigned j = 0; j < MAX; ++j) {
std::uint16_t const a = static_cast<std::uint16_t>(i);
std::uint16_t const b = static_cast<std::uint16_t>(j);
auto const champion = (a + (b & 255)) & 255;
auto const challenger = (a + b) & 255;
if (champion == challenger) { continue; }
std::cout << "a: " << a << ", b: " << b << ", champion: "
<< champion << ", challenger: " << challenger << "\n";
return 1;
}
}
std::cout << "Equality holds\n";
return 0;
}
І ще раз, за словами Кланга : рівність має місце .
Ну ось і ви :)
1 Звичайно, якщо програма коли-небудь випадково викликає невизначену поведінку, це не доведе багато.
Math.random()
повертати ціле число або подвійні на [0,1)? Я не думаю, що ваш сценарій (найкраще, що я можу сказати) взагалі відображає проблему, яку ви поставили.