Eu tinha um código simples que deveria ser um loop infinito, pois x
sempre estará crescendo e sempre permanecerá maior que j
.
int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
x = x + y;
}
System.out.println(y);
mas como está, ele imprime y
e não faz loop indefinidamente. Eu não consigo descobrir o porquê. No entanto, quando ajusto o código da seguinte maneira:
int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
x = x + y;
System.out.println(y);
}
System.out.println(y);
Torna-se um ciclo sem fim e não tenho ideia do porquê. O java reconhece que é um loop infinito e o ignora na primeira situação, mas precisa executar uma chamada de método na segunda para que se comporte conforme o esperado? Confuso :)
java
for-loop
infinite-loop
Omar
fonte
fonte
x
cresce mais rápido do que a variável do loopj
. Em outras palavras,j
nunca atingirá um limite superior, portanto, o loop será executado "para sempre". Bem, não para sempre, você provavelmente terá um estouro em algum ponto.y
238609294 vezesSystem.out.println(x)
vez dey
no final, teria mostrado instantaneamente qual era o problemaRespostas:
Ambos os exemplos não são infinitos.
O problema é a limitação do
int
tipo em Java (ou praticamente qualquer outra linguagem comum). Quando o valor dex
atingir0x7fffffff
, adicionar qualquer valor positivo resultará em estouro e ox
torna - se negativo, portanto menor quej
.A diferença entre o primeiro e o segundo loop é que o código interno leva muito mais tempo e provavelmente levaria vários minutos até
x
estourar. Para o primeiro exemplo, pode levar menos de um segundo ou muito provavelmente o código será removido pelo otimizador, pois não tem nenhum efeito.Conforme mencionado na discussão, o tempo dependerá muito de como o SO armazena a saída, se ela é enviada para o emulador de terminal etc., portanto, pode ser muito maior do que alguns minutos.
fonte
println()
no Windows é uma operação de bloqueio, enquanto em (alguns?) Unix ele é armazenado em buffer e é muito mais rápido. Também tente usarprint()
, que buffers até atingir um\n
(ou o buffer se encher ouflush()
ser chamado)Uma vez que eles são declarados como int, assim que atingir o valor máximo, o loop será interrompido e o valor x se tornará negativo.
Mas quando System.out.println é adicionado ao loop, a velocidade de execução se torna visível (já que a saída para o console diminuirá a velocidade de execução). No entanto, se você deixar o segundo programa (aquele com syso dentro do loop) funcionar por tempo suficiente, ele deverá ter o mesmo comportamento do primeiro (aquele sem syso dentro do loop).
fonte
Pode haver dois motivos para isso:
Java otimiza o
for
loop e, como não há uso dex
after the loop, simplesmente remove o loop. Você pode verificar isso colocandoSystem.out.println(x);
instrução após o loop.Pode ser possível que o Java não esteja realmente otimizando o loop e esteja executando o programa corretamente e, eventualmente,
x
ficará grande demais paraint
estourar. O estouro de inteiro provavelmente tornará o inteirox
negativo, o que será menor que j e, portanto, sairá do loop e imprimirá o valor dey
. Isso também pode ser verificado adicionandoSystem.out.println(x);
após o loop.Além disso, mesmo no primeiro caso, eventualmente, o estouro ocorrerá, tornando-o no segundo caso, de forma que nunca será um verdadeiro loop infinito.
fonte
sysout
é tão lento para adicionar a ilusão de um loop infinito.Ambos não são loops infinitos, inicialmente j = 0, enquanto j <x, j aumenta (j ++), ej é um número inteiro, então o loop seria executado até atingir o valor máximo e então estouraria (Um estouro de inteiro é a condição que ocorre quando o resultado de uma operação aritmética, como multiplicação ou adição, excede o tamanho máximo do tipo inteiro usado para armazená-lo.). para o segundo exemplo, o sistema apenas imprime o valor de y até que o loop seja interrompido.
se você estiver procurando por um exemplo de loop infinito, deve ser parecido com este
porque (x) nunca alcançaria o valor de 10;
você também pode criar um loop infinito com um loop for duplo:
este laço é infinito porque o primeiro laço for diz i <10, o que é verdade, então ele vai para o segundo laço for e o segundo laço for aumenta o valor de (i) até que seja == 5. Então ele prossegue para o primeiro loop for novamente porque i <10, o processo continua se repetindo porque ele reinicia após o segundo loop for
fonte
É um loop finito porque uma vez que o valor de
x
excede2,147,483,647
(que é o valor máximo de anint
),x
se tornará negativo e não maior do quej
qualquer mais, quer você imprima y ou não.Você pode apenas alterar o valor de
y
para100000
e imprimiry
no loop e o loop será interrompido muito em breve.A razão pela qual você acha que ele se tornou infinito é que ele
System.out.println(y);
fez o código ser executado muito mais lento do que sem nenhuma ação.fonte
Problema interessante Na verdade, em ambos os casos, o loop não é infinito
Mas a principal diferença entre eles é quando terminará e quanto tempo
x
levará para exceder oint
valor máximo que é2,147,483,647
depois disso atingirá o estado de estouro e o loop terminará.A melhor maneira de entender esse problema é testar um exemplo simples e preservar seus resultados.
Exemplo :
Resultado:
Depois de testar este loop infinito, levará menos de 1 segundo para terminar.
Resultado:
Neste caso de teste, você notará uma grande diferença no tempo necessário para encerrar e concluir a execução do programa.
Se você não tiver paciência, pensará que esse loop é interminável e não terminará, mas na verdade levará horas para terminar e atingir o estado de estouro no
i
valor.Finalmente concluímos, depois de colocar a instrução print dentro do loop for, que levará muito mais tempo do que o loop no primeiro caso sem a instrução print.
O tempo necessário para executar o programa depende das especificações do seu computador, em particular da capacidade de processamento (capacidade do processador), do sistema operacional e do IDE que está compilando o programa.
Eu testo este caso em:
Lenovo 2.7 GHz Intel Core i5
SO: Windows 8.1 64x
IDE: NetBeans 8.2
Demora cerca de 8 horas (486 minutos) para terminar o programa.
Além disso, você pode notar que o incremento de passo no loop for
i = i + 1
for é um fator muito lento para atingir o valor máximo int.Podemos alterar esse fator e tornar o incremento de etapa mais rápido para testar o loop em menos tempo.
se colocarmos
i = i * 10
e testarmos:Resultado:
Como você pode ver, é muito rápido em comparação com o loop anterior
leva menos de 1 segundo para encerrar e concluir a execução do programa.
Após este exemplo de teste, acho que deve esclarecer o problema e provar a validade de Zbynek Vyskovsky - a resposta do kvr000 , também será a resposta a esta pergunta .
fonte