Você já tem a resposta inteligente: aritmética sem sinal é aritmética de módulo e, portanto, os resultados serão válidos, você pode provar isso matematicamente ...
Uma coisa legal sobre computadores, porém, é que eles são rápidos. Na verdade, eles são tão rápidos que enumerar todas as combinações válidas de 32 bits é possível em um período de tempo razoável (não tente com 64 bits).
Então, no seu caso, eu pessoalmente gosto de apenas jogá-lo em um computador; levo menos tempo para me convencer de que o programa está correto do que para me convencer de que a prova matemática está correta e que não supervisionei um detalhe na especificação 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;
}
Isso enumera todos os valores possíveis de a
e b
no espaço de 32 bits e verifica se a igualdade é mantida ou não. Caso contrário, ele imprime o gabinete que não funcionou, que você pode usar como uma verificação de integridade.
E, de acordo com Clang : a igualdade é mantida .
Além disso, dado que as regras aritméticas são agnósticas quanto à largura de bits (acima int
da largura de bit), essa igualdade se manterá para qualquer tipo de inteiro sem sinal de 32 bits ou mais, incluindo 64 bits e 128 bits.
Nota: Como um compilador pode enumerar todos os padrões de 64 bits em um período de tempo razoável? Eu não posso. Os loops foram otimizados. Caso contrário, todos nós teríamos morrido antes do término da execução.
Inicialmente, provei isso apenas para inteiros sem sinal de 16 bits; infelizmente C ++ é uma linguagem insana para a qual pequenos inteiros (larguras de bits menores que int
) são convertidos primeiro 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;
}
E mais uma vez, de acordo com Clang : a igualdade é válida .
Bem, aí está :)
1 É claro que, se um programa acionar inadvertidamente o comportamento indefinido, isso não provaria muito.
Math.random()
um número inteiro ou duplo em [0,1)? Não acho que seu roteiro (melhor que eu saiba) reflete o problema que você colocou.