1. Encapsule o código do algoritmo de raiz quadrada em uma função. Essa função deve retornar um número de ponto flutuante (float), de forma que possa ser usada em expressões matemáticas (por exemplo, para calcular x \sqrt{2}+z \sqrt{y} ). Ou seja, a assinatura dessa função deve ser compatível com o math. sqrt.

Passo 1

O que o enunciado pede e quais são as informações dadas.
  • Pede para encapsular o algoritmo de raiz quadrada em uma função que:
    • tenha assinatura compatível com math.sqrt (ou seja, receba um único argumento e retorne um float);
    • possa ser usada em expressões matemáticas como, por exemplo, x\sqrt{2}+z\sqrt{y}.
  • Informação implícita importante: a função deve aceitar números não negativos e devolver a raiz quadrada como ponto flutuante; para entradas inválidas (por exemplo, números negativos) devemos sinalizar erro, tal como math.sqrt faz.

Passo 2

Escolha do método para calcular a raiz quadrada (explicação sucinta e por que escolhi esse método).
  • Vou usar o método de Newton–Raphson (também chamado de método babilônico para raízes quadradas). Motivos:
    • É simples e rápido (converge quadráticamente perto da solução);
    • Só precisa de operações básicas (adição, divisão, multiplicação), então pode ser implementado sem bibliotecas especiais;
    • É fácil controlar tolerância e número máximo de iterações para garantir retorno em tempo finito.
  • Não usei métodos mais complicados (por exemplo, aproximações por séries ou manipulação bit a bit) porque Newton é suficiente, claro e fácil de explicar.

Passo 3

Princípio matemático do método Newton para raiz quadrada (aula curta e intuitiva).
  • Queremos encontrar t tal que t^2 = S, onde S é o número cuja raiz queremos.
  • Definimos a função \displaystyle f(t)=t^2-S. A raiz de f é a raiz quadrada de S.
  • A iteração de Newton para resolver f(t)=0 é t_{n+1} = t_n - \frac{f(t_n)}{f'(t_n)}.
  • Aqui f'(t)=2t. Substituindo: t_{n+1} = t_n - \frac{t_n^2 - S}{2t_n} = \frac{1}{2}\left(t_n + \frac{S}{t_n}\right).
  • Essa fórmula é a iteração babilônica: t_{n+1} = \frac{t_n + S/t_n}{2}.
  • Intuição: cada iteração combina o chute atual t_n com S/t_n (um outro chute), fazendo uma média que tende rapidamente à raiz.

Passo 4

Critério de parada e cuidados numéricos (como saber quando parar e tratar casos especiais).
  • Critério prático: parar quando a mudança entre iterações for pequena o suficiente, por exemplo quando |t_{n+1}-t_n| \le \text{tol} \cdot \max(1, t_{n+1}),onde tol é uma tolerância pequena (por exemplo 10^{-12}). Usei esse critério relativo para funcionar bem tanto para números grandes quanto pequenos.
  • Também posso checar o erro relativo em termos de t_n^2: |t_n^2 - S| \le \text{tol} \cdot \max(1, S). Ambos funcionam; escolhi o primeiro por simplicidade de implementação.
  • Casos especiais:
    • Se S=0 devolvemos 0.0 imediatamente.
    • Se S<0 devemos levantar um erro (no Python math.sqrt levanta ValueError: math domain error).
    • Converge rápido, mas vou colocar um limite máximo de iterações (por exemplo, 100) para garantir que a função sempre retorne em tempo finito.

Passo 5

Detalhamento linha-a-linha do que a função fará (decisões de implementação que você precisa entender na prova).
  • Entrada:
    • Receber um argumento x. Converter para float para garantir que o retorno seja float e para permitir entrada de inteiros.
    • Se a conversão falhar (por exemplo, string não numérica), propagar um TypeError/ValueError apropriado.
  • Verificações iniciais:
    • Se x < 0: levantar ValueError("math domain error").
    • Se x == 0.0: retornar 0.0.
  • Chute inicial (t0):
    • Uma escolha simples e eficiente é t0 = x quando x >= 1.0, caso contrário t0 = 1.0. Isso evita divisão por zero e melhora a convergência para números pequenos.
  • Iteração:
    • Aplicar a fórmula t_{n+1} = 0{,}5\,(t_n + x/t_n) até o critério de parada ou até atingir o número máximo de iterações.
  • Retorno:
    • Retornar o valor final como float.
  • Mensagem de erro:
    • Para números negativos use ValueError("math domain error") para ficar coerente com math.sqrt.

Passo 6

Observações práticas rápidas para a prova e uso em expressões.
  • A função com essa assinatura (def sqrt(x): ...) pode ser usada diretamente em expressões como x\sqrt{2}+z\sqrt{y} em Python escrevendo, por exemplo:
    • x * sqrt(2) + z * sqrt(y)
  • O método é robusto para maioria dos casos reais que aparecerão numa prova de programação numérica; se quiser maior precisão, basta reduzir tol (mas cuidado com o número de iterações).

Resposta

def sqrt(x):
    """Compute the square root of x (similar signature to math.sqrt).
    Returns a float. Raises ValueError("math domain error") for x < 0.
    """
    # tentativa de conversão para float (levanta TypeError/ValueError se inválido)
    try:
        x = float(x)
    except Exception:
        raise TypeError("must be a real number") from None

    if x < 0.0:
        raise ValueError("math domain error")
    if x == 0.0:
        return 0.0

    # parâmetros do método
    tol = 1e-12
    max_iter = 100

    # chute inicial: escolha simples que funciona bem na prática
    t = x if x >= 1.0 else 1.0

    for _ in range(max_iter):
        next_t = 0.5 * (t + x / t)
        # critério de parada relativo
        if abs(next_t - t) <= tol * max(1.0, next_t):
            return float(next_t)
        t = next_t

    # se não convergir dentro de max_iter, devolve o melhor chute
    return float(t)

Exercícios relacionados