Bom dia!
Atualizei o bloco Acompanhamento das aulas com o material dessa semana. Em particular, gostaria de relembrar que escrevemos um código para a função raizquadrada ontem que gerava um laço infinito ao tentarmos calcular raizquadrada(2). Isso ocorria porque y se aproximava rapidamente da raiz de 2, mas a precisão finita da representação em ponto flutuante torna praticamente impossível que a condição y**2==x se verifique exatamente, fazendo com que y**2!=x seja sempre True. Curiosamente, existem muitos números inteiros para os quais o programa não para (você consegue produzir outros?) e muitos números quebrados para os quais o programa para (tente produzir exemplos). Mais ainda, existe uma lógica bem forte para cada um desses casos, e a chave do mistério está na representação binária das soluções (pense que mesmo números fracionários também são representados em binário, usando as potências negativas de 2: 0.5, 0.25, 0.125, 0.0625...).
Um exercício sugerido para vocês é re-escrever o programa fazendo com que ele pare sempre, usando uma versão aproximada daquela condição do while. Existem formulações alternativas para a condição de parada que pedem para verificar se duas aproximações sucessivas y[k] e y[k+1] = (y[k]+x/y[k])/2 estão próximas o suficiente uma da outra. No caso da raiz quadrada, relaxar a condição y**2==x parece até mais interessante, pois nos dá uma medida exata do desvio em relação ao valor real da raiz quadrada (ao invés de simplesmente constatar que a sequência começou a dar passos muito pequenos e "ficou com preguiça", o que por si só não seria garantia de estarmos muito perto da solução). Um desafio experimental interessante consiste em fazer implementações das duas condições usando uma mesma tolerância/precisão, e ver quão bem a solução de um código verifica a condição do outro código: se a solução verifica a condição y**==x com um erro menor do que 1e-6 (==10-6), qual foi a diferença entre as últimas duas aproximações produzidas? e se as duas últimas aproximações distam menos de 1e-6 uma da outra, qual o erro entre y**2 e x?
Para a cultura geral de vocês, esse método para calcular a raiz quadrada, que pode ser derivado do método de Newton para obter zeros de funções, era conhecido desde o tempo dos Babilônios. O método de Newton permite obter iterações para construir sequências que aproximam muitas funções, em particular a raiz n-ésima de um x qualquer: basta fazer um chute inicial x0 (que pode ser o próprio x) e construir a sequência y[k+1] = ((n-1)*y[k]+x/y[k]**(n-1))/n. No link existe a dedução da expressão, que depende apenas de conhecer derivadas de polinômios (Calculus to the rescue!
). Experimente escrever uma função raizgeral(x,n) que produza essas aproximações.
Boas implementações!
Marcelo