Vous avez déjà la réponse intelligente: l'arithmétique non signée est l'arithmétique modulo et donc les résultats tiendront, vous pouvez le prouver mathématiquement ...
Une chose intéressante à propos des ordinateurs, cependant, est que les ordinateurs sont rapides. En effet, ils sont si rapides qu'il est possible d'énumérer toutes les combinaisons valides de 32 bits dans un laps de temps raisonnable (n'essayez pas avec 64 bits).
Donc, dans votre cas, j'aime personnellement le lancer sur un ordinateur; il me faut moins de temps pour me convaincre que le programme est correct qu'il n'en faut pour me convaincre que la preuve mathématique est correcte et que je n'ai pas supervisé un détail dans la spécification 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;
}
Cela énumère toutes les valeurs possibles de a
et b
dans l'espace de 32 bits et vérifie si l'égalité est vraie ou non. Si ce n'est pas le cas, il imprime le cas qui n'a pas fonctionné, que vous pouvez utiliser comme contrôle de cohérence.
Et, selon Clang : l' égalité tient .
En outre, étant donné que les règles arithmétiques sont indépendantes de la largeur en bits (au int
- dessus de la largeur en bits), cette égalité sera valable pour tout type entier non signé de 32 bits ou plus, y compris 64 bits et 128 bits.
Remarque: Comment un compilateur peut-il énumérer tous les modèles 64 bits dans un délai raisonnable? Ça ne peut pas. Les boucles ont été optimisées. Sinon, nous serions tous morts avant la fin de l'exécution.
Au départ, je ne l'ai prouvé que pour les entiers non signés 16 bits; Malheureusement, C ++ est un langage insensé dans lequel les petits entiers (plus petits bits que int
) sont d'abord convertis 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;
}
Et encore une fois, selon Clang : l' égalité tient .
Eh bien, voilà :)
1 Bien sûr, si un programme déclenche par inadvertance un comportement indéfini, cela ne prouverait pas grand-chose.
Math.random()
un entier ou un double sur [0,1)? Je ne pense pas que votre scénario (le mieux que je puisse dire) reflète le problème que vous avez posé.