O seguinte bloco de códigos fornece a saída como 0.
public class HelloWorld{
public static void main(String []args){
int product = 1;
for (int i = 10; i <= 99; i++) {
product *= i;
}
System.out.println(product);
}
}
Por favor, alguém pode explicar por que isso acontece?
java
integer
integer-overflow
Aniruddha Sarkar
fonte
fonte
2
exibido cerca de 90 vezes. Isso significa que você precisará de uma variável com pelo menos 90 bits para obter uma saída diferente de zero. 32 e 64 têm menos de 90. Para calcular números inteiros maiores que as palavras nativas, você deve usar qualquer classe inteira grande que esteja disponível no idioma escolhido.Respostas:
Aqui está o que o programa faz em cada etapa:
Observe que em algumas etapas a multiplicação resulta em um número menor (980179200 * 18 = 463356416) ou sinal incorreto (213837312 * 20 = -18221056), indicando que houve um estouro de número inteiro. Mas de onde vem o zero? Leia.
Tendo em mente que
int
tipo de dados é um 32-bit assinado , dois complemento inteiro, aqui está uma explicação de cada etapa:Sabemos que multiplicar um número por um número par:
Então, basicamente, seu programa multiplica um número par por outro número repetidamente, o que zera os bits do resultado começando da direita.
PS: Se as multiplicações envolverem números ímpares, o resultado não será zero.
fonte
A multiplicação por computador está realmente acontecendo no módulo 2 ^ 32. Depois de acumular potências suficientes de dois no multiplicando, todos os valores serão 0.
Aqui temos todos os números pares da série, junto com a potência máxima de dois que divide o número e a potência acumulada de dois
O produto até 42 é igual a x * 2 ^ 32 = 0 (mod 2 ^ 32). A sequência dos poderes de dois está relacionada aos códigos de Gray (entre outras coisas) e aparece como https://oeis.org/A001511 .
EDIT: para ver por que outras respostas a esta pergunta estão incompletas, considere o fato de que o mesmo programa, restrito apenas a números ímpares, não convergiria para 0, apesar de todo o transbordamento.
fonte
Parece um estouro inteiro .
Dê uma olhada neste
Resultado:
A saída não será mais um
int
valor. Então você obterá um valor errado por causa do estouro.Mais informação
Edit .
Vamos mudar seu código da seguinte maneira
Resultado:
fonte
É por causa do estouro inteiro. Quando você multiplica muitos números pares, o número binário recebe muitos zeros à direita. Quando você tem mais de 32 zeros à direita para um
int
, ele passa para0
.Para ajudá-lo a visualizar isso, aqui estão as multiplicações em hexadecimal calculadas em um tipo de número que não transbordará. Veja como os zeros à direita crescem lentamente e observe que um
int
é composto dos últimos 8 dígitos hexadecimais. Após multiplicar por 42 (0x2A), todos os 32 bits de umint
são zeros!fonte
Em algum lugar no meio, você obtém
0
o produto. Portanto, todo o seu produto será 0.No seu caso :
Toda vez que você multiplica o valor atual de
i
com o número que você obtém0
como saída.fonte
Como muitas das respostas existentes apontam para detalhes de implementação de Java e saída de depuração, vamos dar uma olhada na matemática por trás da multiplicação binária para realmente responder ao porquê.
O comentário de @kasperd vai na direção certa. Suponha que você não se multiplique diretamente com o número, mas com os fatores primos desse número. Muitos números terão 2 como fator primordial. Em binário, isso é igual a um deslocamento para a esquerda. Pela comutatividade, podemos multiplicar os fatores primos de 2 primeiro. Isso significa que apenas fazemos um desvio à esquerda.
Ao examinar as regras de multiplicação binária, o único caso em que um 1 resultará em uma posição específica de dígito é quando ambos os valores do operando são um.
Portanto, o efeito de um deslocamento para a esquerda é que a posição de bit mais baixa de 1 ao multiplicar ainda mais o resultado é aumentada.
Como o número inteiro contém apenas os bits de ordem mais baixa, todos eles serão configurados para 0 quando o fator principal 2 for co-retido com frequência suficiente no resultado.
Observe que a representação do complemento de dois não é interessante para esta análise, pois o sinal do resultado da multiplicação pode ser calculado independentemente do número resultante. Isso significa que se o valor exceder o valor e se tornar negativo, os bits de ordem mais baixa serão representados como 1, mas durante a multiplicação, eles serão tratados novamente como sendo 0.
fonte
Se eu executar esse código O que eu recebo tudo -
Causa de estouro de número inteiro -
Produzir 0 causa -
fonte
Eventualmente, o cálculo transborda e, eventualmente, esse transbordo leva a um produto zero; isso acontece quando
product == -2147483648
ei == 42
. Experimente este código para verificar por si mesmo (ou execute o código aqui ):Uma vez que é zero, é claro que permanece zero. Aqui está um código que produzirá um resultado mais preciso (você pode executar o código aqui ):
fonte
É um estouro inteiro.
O tipo de dados int é 4 bytes ou 32 bits. Portanto, números maiores que 2 ^ (32 - 1) - 1 (2.147.483.647) não podem ser armazenados nesse tipo de dados. Seus valores numéricos estarão incorretos.
Para números muito grandes, convém importar e usar a classe
java.math.BigInteger:
NOTA: Para valores numéricos ainda grandes demais para o tipo de dados int, mas pequenos o suficiente para caber em 8 bytes (valor absoluto menor ou igual a 2 ^ (64 - 1) - 1), você provavelmente deve usar a
long
primitiva.Os problemas de prática do HackerRank (www.hackerrank.com), como a seção prática de algoritmos, ( https://www.hackerrank.com/domains/algorithms/warmup ) incluem algumas perguntas de grande número muito boas que fornecem boas práticas sobre como pense no tipo de dados apropriado a ser usado.
fonte