possibilidade de loop while vs for loop

8

Eu tenho esse professor, ele é bastante inteligente (às vezes, haha), ele disse que bons programadores tentam usar whileloops em vez de forloops. a razão que ele deu para isso é porque os whileloops podem ser comprovados, como em, pode-se explicar completamente o que acontece em um whileloop, enquanto você não pode fazer isso para um forloop. ele também disse algo sobre os programadores da NASA que usam apenas whileloops e não têm permissão para fazer forloops por causa disso.

Eu tenho dificuldade em entender isso, pois ambos os loops podem ser explicados como eles funcionam em detalhes, certo? para ambos, você sempre saberia o que vai acontecer?

alguém pode me explicar por que os whileloops podem ser comprovados (e, por isso, pode ser melhor do que os forloops, pelo menos em alguns casos).

EDIT:
talvez ele estivesse se referindo a:
2: Todos os loops devem ter um limite superior fixo. Deve ser trivialmente possível para uma ferramenta de verificação provar estaticamente que um limite superior predefinido no número de iterações de um loop não pode ser excedido. Se o limite do loop não puder ser provado estaticamente, a regra será considerada violada.

Embora isso ainda não diga nada sobre a diferença entre while e for loops.

Vincent
fonte
17
Seu professor está completamente errado ou você relatou mal o que ele disse de alguma forma. Essa justificativa para preferir forao invés de whilesimplesmente não faz sentido. Pode haver um, mas não é isso.
Kilian Foth
7
Eu concordo com Kilian. Não faz sentido que deve haver uma diferença, como for (init; test; step) { body }tem um Dessacarificação trivial while: {init; while (test) { step; body }}.
1
Para (;;) {cout << "eles realmente não são tão diferentes" << endl;}. A maior diferença é que, para loops, você mantém facilmente uma variável (i) no escopo do loop.
Nathan Cooper
2
@MikeNakis, pelo contrário. Um culter de carga não faria a pergunta, apenas perpetuando mitos. Talvez até punir os outros por não "aderirem à regra".
sehe
2
@ MikeNakis Não sei se temos informações suficientes para avaliar a mentalidade do professor.
sehe

Respostas:

13

Em poucas palavras : o que seu professor provavelmente quis dizer é que a semântica de whileé praticamente a mesma na maioria dos idiomas, enquanto a semântica de forpode mudar consideravelmente (veja a discussão abaixo). Portanto, a prova independente da linguagem abstrata é mais confiável com a while, mas é preciso ter cuidado para que uma prova com um forloop possa não corresponder à semântica do forloop em muitos idiomas.

Sua pergunta não é precisa o suficiente (embora isso possa não ser sua culpa).

O ponto é que, depois, não existe um padrão oficial suportado pela ISO ou outra definição de referência fore whileloops oficialmente aceitos . A definição depende da linguagem de programação.

Portanto, você não pode fazer nenhuma declaração geral sobre sua equivalência antes de definir com precisão o que cada um pode fazer. Abordo isso com mais precisão, já que é um dos principais argumentos usados ​​em outras respostas (e a discussão será útil a seguir).

Sobre intertranslatabilidade de fore whileloops

Resumo : depende da linguagem de programação, mas sempre é possível desde que você possa ter um loop infinito e uma maneira de sair dele.

Mas você pode fazer essa afirmação para uma linguagem de programação específica, e a resposta dependerá dos recursos da linguagem.

Isso também significa que não há provas gerais, mas apenas uma para cada linguagem de programação.

Uma coisa que geralmente é verdadeira é que um whileloop geralmente pode imitar um forloop, porque o loop while pode fazer o teste da condição de saída do loop for, fazendo a inicialização da variável de controle com uma atribuição antes de entrar no loop e fazendo a incrementação no final do corpo do loop, para que

for i from 1 by 2 to 10 do { xxx }

torna-se

i=1
while i≤11 do { xxx; i←i+2 }

Isso funciona mais ou menos para a maioria dos idiomas, mas não é tão óbvio quanto parece, e pode haver muitos "detalhes" com que se preocupar.

Por exemplo, em muitos idiomas, o forloop avalia três argumentos (valor inicial, incremento e valor final) como argumentos estritos , avaliados uma vez antes de entrar no loop, enquanto outros consideram argumentos thunk para serem reavaliados a cada turno, ou possivelmente como argumento preguiçoso para ser avaliado apenas quando necessário.

Outro ponto pode ser que a variável de incremento possa ser local para o forloop ou precise ser uma variável local da função em que o loop aparece.

Dependendo de tais questões, a tradução de a forpara a whilepode variar muito, embora seja geralmente possível alcançá-la.

O mesmo vale para o inverso, traduzindo um whilepara um forloop.

O primeiro problema é que um whileloop sempre reavaliará a condição de saída a cada turno. Mas alguns forloops não fornecem uma condição que é reavaliada a cada turno, exceto a comparação da variável de controle com algum valor fixo calculado na entrada do loop. Portanto, a tradução não é possível, a menos que haja outro meio de sair do loop em algumas condições arbitrárias.

Isso é possível com vários dispositivos, geralmente começando com uma instrução condicional testando a condição, seguida de um salto implementado, conforme disponível, por uma instrução de saída do loop, uma instrução de retorno (depois de encapsular o loop em uma função), uma instrução goto ou um aumento de exceção.

Em outras palavras, é novamente muito dependente de idiomas e, possivelmente, de recursos sutis dos idiomas.

Dito isto, como respondido por @milleniumbug , a intertradução é fácil na linguagem C, porque um forlopp é essencialmente um whileloop mais alguns extras para uma variável de controle incrementada.

Mas isso não se aplica necessariamente a outros idiomas e, provavelmente, não da mesma maneira.

Dito isto, as linguagens de programação geralmente têm poder de Turing com apenas um desses loops, pois tudo o que você precisa é de um loop infinito. Portanto, desde que você tenha alguma maneira de repetir para sempre e possivelmente decidir parar, você tem certeza de que pode imitar qualquer outra construção ... mas não necessariamente facilmente.

Em relação às provas

Resumo : Não há razão para mim afirmar que as provas devem ser significativamente mais difíceis com uma ou outra (a menos que haja algum recurso estranho da linguagem).

Provavelmente há um mal-entendido, ou seu professor estava pensando em outra coisa.

A semântica de elementos formais pode ser definida para os vários tipos de loops definidos nas linguagens de programação e, em seguida, usada para provar propriedades.

Pode ser, novamente, dependendo do idioma, que a realização de provas formais sobre os programas possa ser mais complexa em alguns casos. Mas isso depende do idioma.

Não consigo imaginar uma razão pela qual as provas devam ser significativamente mais difíceis com um construto do que com o outro. O forloop pode ser mais complexo, pois pode oferecer, como em C, tudo o que é feito com whileoutras coisas. Mas se você fizesse isso com a while, teria que adicionar os extras de alguma outra forma.

Eu poderia usar o argumento geral formal de intertraduzibilidade, desde que haja a possibilidade de um único loop infinito. No entanto, evitarei fazer isso, pois as construções envolvidas não são nada com que você queira lidar com uma prova e seria claramente uma afirmação injusta, pelo menos na prática.

Após a discussão acima, no entanto, vimos que as dificuldades para a intertradução resultam da grande variabilidade do forloop de linguagem para linguagem. Daí a seguinte conclusão, que provavelmente é a resposta certa:

Uma possibilidade de entender a afirmação do professor é que a semântica do whileloop é praticamente a mesma em todas as linguagens de programação, enquanto a sintaxe e a semântica do forloop podem variar significativamente de idioma para idioma. Portanto, é possível fazer provas "abstratas" gerais com whileloops que tenham uma semântica independente da linguagem em boa medida, enquanto isso não é possível para o forloop que tem sintaxe e semântica mudando muito de idioma para idioma. Mas isso não se aplica a um determinado idioma, quando a semântica de ambos é definida com precisão.

Minha melhor sugestão é que você pergunte ao seu professor o que ele quis dizer com precisão e se ele pode lhe dar um exemplo. Erros de interpretação ou mal-entendidos são um evento comum.

babou
fonte
1
@VincentAdvocaat Bem, o site é para todos os usuários, não apenas para o Pôster original da pergunta. Foi por isso que eu fiz. Eu também sinalizei minha própria resposta para o moderador pará-la se inadequada. Na verdade, foi uma pergunta interessante, e levei algum tempo para chegar à minha conclusão ... esperando que seja a certa. Deixe-nos saber se você descobrir.
babou
Acabei de notar a edição que você fez uma hora atrás, adicionando o que você declara em sua resposta aqui. Essa é realmente a melhor resposta possível à minha pergunta e agradeço por isso. No que diz respeito à atenção do moderador, é mais minha culpa por criar uma duplicata entre vários sites SE. Portanto, para isso não vejo razão para excluir esta resposta, se algo deve ser excluído, teria que ser a 2ª pergunta que fiz, mas como a sua resposta é bem formulada e explica a afirmação feita aqui em profundidade, não acho sensato. para remover qualquer um. a menos que você adicione as informações a esta pergunta.
Vincent
1
Não faço ideia, coisas estranhas acontecem, sempre divertidas quando as pessoas não explicam nenhuma razão para isso.
Vincent
3
Aconteceu novamente: 1 para cima + 1 para baixo. O que me incomoda é que está prejudicando o site mais do que eu. Eu tento escrever respostas completas que ajudam as pessoas. Se houver alguma falha, seria mais sábio comentar para me dar uma oportunidade de corrigir. Se houver outro motivo, apenas reduz a atratividade de uma resposta que possa ser útil, às custas do site. Gostaria de saber se a substituição da resposta estendida ou a remoção do aviso no final têm algo a ver com isso. Mas o moderador parecia bem com a situação.
babou
1
Como moderador, gosto da sua resposta e aprendi algo ao lê-la. É uma boa resposta
maple_shaft
12

Na linguagem C, você pode reescrever cada forloop em um whileloop equivalente e vice-versa.

while -> for transformação:

Reescrever

while(condition) { instructions; }

para

for(; condition; ) { instructions; }

for -> while transformação:

Isso é um pouco mais complicado, especialmente se você tiver uma continuedeclaração no seu loop.

Reescrever:

for(init; condition; next) { instructions; }

para:

{
    init;
    while(condition)
    {
        instructions;
    next_label:
        next;
    }
}

mas substitua toda continue;declaração por goto next_label;declaração. Se conditionfor uma instrução nula, substitua-a por true.

Como você pode ver, na linguagem C, nenhum dos dois é mais "provável" (o que quer que isso signifique) do que o outro, pois, mesmo que um dos loops fosse, você poderia reescrevê-lo em termos de outro loop.

Agora, existem outros idiomas onde essa while <-> forequivalência não existe. Por exemplo, em Pascal, você pode assumir mais informações sobre o forloop. Isso significa que você não pode expressar todos os conceitos ao escrever um forloop, mas pode provar mais sobre o fluxo do código:

for i:=1 to n do
    instructions;

Aqui, o né salvo no início do loop, para que as alterações nnão influenciem a iteração e você não possa modificar ino corpo do loop. Isso significa que você pode provar trivialmente que esse loop acabará eventualmente (como né finito e não pode ser modificado i).

milleniumbug
fonte
Reescrever alguns loops "for" como "while" exigiria duplicação de código, adição de sinalizadores ou adição goto. Se adicionarmos sinalizadores, todos os outros loops poderão ser emulados usando um único "while (1) ..." em torno de uma função que será executada até um "retorno"; se adicionar "goto", todos os outros loops podem ser emulados usando isso.
26616
Obrigado por provar meu argumento. Copiar e colar o fragmento de código A não altera minha capacidade de raciocinar sobre isso.
precisa
De fato, copiar / colar não altera a capacidade de raciocinar sobre o código, mas é um motivo importante para não considerar "for" como uma construção de linguagem supérflua, pois um dos objetivos de design de uma boa linguagem de programação deve ser minimizar a necessidade de copiar / colar.
Supercat
7

Na lógica de Floyd-Hoare , o sistema formal mais comum de raciocínio sobre a correção de programas de computador, existe a regra while .

Em palavras, se você tiver uma cláusula de guarda (a expressão entre colchetes no while()), uma função variante (uma expressão com valores discretos que podem ser mostrados para diminuir monotonicamente toda vez que o loop for executado e sempre seja positivo) e um loop invariável (uma declaração lógica que sempre é verdadeira antes e depois de cada vez que o loop é executado), você pode provar que o loop while terminará (porque a função variante não pode continuar diminuindo) e que, eventualmente, a cláusula guard será falsa e o loop invariável seja verdadeiro.

A lógica de Floyd-Hoare não possui regras para forloops ou quaisquer construções que as linguagens reais possam ter.

No entanto, como outras respostas explicam, os loops sempre podem ser escritos em termos de while. Isso significa que eles podem ser fundamentados, basta um pouco mais de trabalho.

Se o seu professor teve cursos na universidade, onde ele teve que fornecer provas de correção de seus programas, ele provavelmente escreveu programas usando apenas loops. Eu sei que sim. E uma vez que você está acostumado a pensar em termos de guardas, funções variantes e invariantes de loop, eles parecem muito naturais. O uso excessivo de loops é um hábito que você vê com os graduados em CS, tive que aprender a parar de fazer isso nos meus primeiros meses como desenvolvedor profissional.

Em algum momento, seu professor se lembrou de tudo isso como "bons programadores usam loops", enquanto o que realmente acontece é mais como "alguns graduados em informática transformam seus hábitos de correção em hábitos práticos de programação".

RemcoGerlich
fonte
Isso parece ser bastante consistente com minha própria avaliação, embora baseado em uma visão diferente. A lógica de Floyd-Hoare não tinha motivos para considerar o forloop, que não tem definição fixa e é mais complexo, sem ser formalmente necessário.
babou
3

Na verdade, em certo sentido, o exato oposto é verdadeiro.

Um idioma com apenas forloops não é completo em Turing, apenas pode calcular as funções primitivas-recursivas, nem todas as funções computáveis ​​em Turing. Como todo o cálculo em uma linguagem com apenas forloops sempre termina, o Problema da Parada e todos os outros Problemas de Decidibilidade com base nele simplesmente não surgem, portanto, é possível decidir mecanicamente muitas propriedades estáticas dos programas do que em uma linguagem com while-rotações.

OTOH, uma linguagem com apenas números naturais, uma única variável e while-loops é Turing-complete e, portanto, não é possível decidir nem a mais simples das propriedades: este programa retornará um resultado?

Jörg W Mittag
fonte
1
Uma forlinguagem apenas pode produzir um whilecomportamento equivalente, diminuindo a variável do loop (assumindo que a linguagem permita) durante iterações que não deveriam resultar em terminação. (Por exemplo, for n in 1 to 2 { if condition then n := n-1 })
Blrfl
Há muitas maneiras pelas quais um loop for pode ser repetido para sempre, dependendo, é claro, de sua definição no idioma em questão. E um loop infinito é suficiente para a perfeição de Turing.
babou
@ababou: A interpretação mais comum de um loop for é um loop que itera sobre um intervalo finito ou coleção. Obviamente, em muitos idiomas, é possível hackear um loop for para se comportar como um loop while, mas acho que não é isso que Jörg tinha em mente.
Giorgio
0

Gostaria de dizer que, na realidade, não há diferença. Sua pergunta é irrelevante. Pode ser que seu professor pretenda usar o loop while, quando não. de iterações não é conhecido de antemão. Em muitos casos, precisamos usar um loop while para extrair dígitos de um não. quando o usuário digita o não. que pode ter qualquer comprimento. Tecnicamente falando, a semelhança entre o loop for & while é que ambos são loops com controle de entrada em que a (expressão / condição de teste) é avaliada antes de entrar no corpo do loop. Essa é a distinção entre loops while & do-while.

Jai Thakur
fonte
-1

Provavelmente, vem da programação C inicial, na qual, pelas normas atuais, os loops foram amplamente abusados ​​e mal utilizados, especialmente a modificação condicional. Quando os programadores começaram a entender o efeito que certos estilos de programação tiveram, o abuso e o uso indevido de condicionais de loop caíram em desuso, e a afirmação, embora (indiscutivelmente) uma vez válida, já não é verdadeira.

A afirmação não tem absolutamente nenhuma verdade se você olhar apenas para a definição e sintaxe da linguagem e ignorar como ela estava sendo usada.

A declaração em si, no entanto, oferece uma lição valiosa para quem quer entendê-la, sua história e por que não é mais considerada verdadeira. - Qual é a expressão sobre aprender, errar e repeti-los .....

mattnz
fonte
-10

Seu professor está correto!

O motivo é o seguinte é C válido

for (int x = 1 ; x < 20 ; x++ ) {
   x = x + 9;
}

Você não pode garantir que as variáveis ​​de condição não foram violadas!

James Anderson
fonte
2
Como isso faz com que os whileloops se saiam melhor aqui?
milleniumbug
7
Oh sim? Visto que, com whileloops, você pode realmente garantir que a variável de condição não foi adulterada? De fato, adulterar a variável de condição é a única maneira de sair de um whileloop! Eu geralmente evito fazer votos negativos, mas para esta resposta, farei uma exceção.
quer
James talvez pudesse elaborar por que isso é menos de um problema pois enquanto loops, você pode estar ligada a algo no entanto as pessoas parecem discordar de uma lac de contra provas no caso de while
Vincent
1
@VincentAdvocaat Eu diria que, com um loop while, você espera que a variável de condição seja violada de alguma forma, enquanto que um loop for, você espera que seja alterado apenas na parte da etapa da construção do loop for. Esse princípio de menor espanto é mais importante do que muitos imaginam na programação.
Gbjbaanb
3
@gbjbaanb é verdade, mas no que diz respeito à questão, está muito longe do princípio de menos espanto e provabilidade.
precisa saber é o seguinte