Sie haben bereits die kluge Antwort: Vorzeichenlose Arithmetik ist Modulo-Arithmetik und daher gelten die Ergebnisse, Sie können es mathematisch beweisen ...
Eine coole Sache an Computern ist jedoch, dass Computer schnell sind. In der Tat sind sie so schnell, dass die Aufzählung aller gültigen Kombinationen von 32 Bit in angemessener Zeit möglich ist (versuchen Sie es nicht mit 64 Bit).
In Ihrem Fall mag ich es persönlich, es einfach auf einen Computer zu werfen. Ich brauche weniger Zeit, um mich davon zu überzeugen, dass das Programm korrekt ist, als um mich selbst zu überzeugen, als der mathematische Beweis korrekt ist und dass ich kein Detail in der Spezifikation 1 übersehen habe :
#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;
}
Dies listet alle möglichen Werte von a
und b
im 32-Bit-Raum auf und prüft, ob die Gleichheit gilt oder nicht. Wenn dies nicht der Fall ist, wird der Fall gedruckt, der nicht funktioniert hat, und der als Überprüfung der geistigen Gesundheit verwendet werden kann.
Und laut Clang : Gleichheit gilt .
Da die arithmetischen Regeln bitbreitenunabhängig sind (über der int
Bitbreite), gilt diese Gleichheit für jeden vorzeichenlosen Integer-Typ von 32 Bit oder mehr, einschließlich 64 Bit und 128 Bit.
Hinweis: Wie kann ein Compiler alle 64-Bit-Muster in einem angemessenen Zeitrahmen auflisten? Es kann nicht. Die Schleifen wurden optimiert. Sonst wären wir alle gestorben, bevor die Hinrichtung beendet war.
Ich habe es zunächst nur für 16-Bit-Ganzzahlen ohne Vorzeichen bewiesen. Leider ist C ++ eine verrückte Sprache, in die zuerst kleine Ganzzahlen (kleinere Bitbreiten als int
) konvertiert werden 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;
}
Und noch einmal laut Clang : Gleichheit gilt .
Na siehst du :)
1 Wenn ein Programm jemals versehentlich undefiniertes Verhalten auslöst, würde es natürlich nicht viel beweisen.
Math.random()
eine Ganzzahl oder ein Doppel bei [0,1) zurück? Ich glaube nicht, dass Ihr Skript (so gut ich es beurteilen kann) das Problem widerspiegelt, das Sie überhaupt gestellt haben.