1. Seja
f(x)=\sqrt{2 x^{2}+1}-\sqrt{x^{2}+1}
Descreve o algoritmo para calcular valor da função f(x) utilizando um sistema de ponto flutuante, tal que o erro relativo do resultado será da ordem do erro da representação.

Passo 1

O enunciado dá a função
f(x)=\sqrt{2 x^{2}+1}-\sqrt{x^{2}+1}
e pede que eu descreva um algoritmo para calcular f(x) num sistema de ponto flutuante de modo que o erro relativo do resultado seja da ordem do erro da representação (ou seja, da ordem do erro de arredondamento do sistema, que denotarei por u).\n
Informações/requisitos explícitos:
\text{dado: }f(x)=\sqrt{2 x^{2}+1}-\sqrt{x^{2}+1}.
\text{objetivo: produzir um algoritmo em ponto flutuante cujo erro relativo final seja }O(u).
Não tenho que usar nenhuma implementação específica; preciso descrever passos numéricos e justificar por que o erro relativo fica da ordem de u.

Passo 2

Por que o cálculo direto é perigoso (intuição e exemplo): se eu calcular diretamente
s_1=\sqrt{2x^2+1},\qquad s_2=\sqrt{x^2+1},\qquad f(x)=s_1-s_2,
posso ter cancelamento catastrófico quando s_1 e s_2 são quase iguais. Vamos ver um caso concreto: para x pequeno, usando expansão em série,
\sqrt{1+t}=1+\tfrac{t}{2}-\tfrac{t^2}{8}+\cdots.
Com t=2x^2 e t=x^2 obtemos, para x pequeno,
\sqrt{2x^2+1}\approx 1+x^2-\tfrac{(2x^2)^2}{8}=1+x^2-\tfrac{x^4}{2}+\cdots,
\sqrt{x^2+1}\approx 1+\tfrac{x^2}{2}-\tfrac{x^4}{8}+\cdots,
logo
f(x)=\sqrt{2x^2+1}-\sqrt{x^2+1}\approx x^2-\tfrac{x^2}{2}=\tfrac{x^2}{2}.
Ou seja, s_1 e s_2 são ambos próximos de 1 e a diferença é da ordem de x^2 — muito menor que os termos que estou subtraindo. Num sistema de ponto flutuante, se s_1 e s_2 são representados com erro relativo O(u) (cada um com erro da ordem de u), o erro absoluto na subtração pode ser da ordem de u, e a divisão desse erro absoluto pelo valor pequeno f(x) pode amplificar o erro relativo em cerca de 1/x^2. Em outras palavras: o cálculo direto pode dar um erro relativo enorme quando x é pequeno.

Passo 3

Ideia chave para evitar cancelamento: manipular algebricamente a expressão para eliminar a subtração de duas quantidades quase iguais. Faço a racionalização:
\begin{aligned} f(x)&=\sqrt{2x^2+1}-\sqrt{x^2+1}\\\ &=\frac{(\sqrt{2x^2+1}-\sqrt{x^2+1})(\sqrt{2x^2+1}+\sqrt{x^2+1})}{\sqrt{2x^2+1}+\sqrt{x^2+1}}\\\ &=\frac{(2x^2+1)-(x^2+1)}{\sqrt{2x^2+1}+\sqrt{x^2+1}}\\\ &=\frac{x^2}{\sqrt{2x^2+1}+\sqrt{x^2+1}}. \end{aligned}
Esta forma evita subtrair duas raízes próximas: o numerador é x^2 (que posso calcular diretamente) e o denominador é soma de duas raízes (não há cancelamento na soma). Para x pequeno, o denominador é aproximadamente 2, então o resultado é aproximadamente x^2/2 calculado sem perda por cancelamento.

Passo 4

Algoritmo numérico estável (estrutura e operações em ponto flutuante). Vou escrever uma versão com dois ramos para evitar overflow quando x for muito grande e para evitar cancelamento quando x for pequeno. Denoto por \operatorname{fl}(\cdot) a operação em ponto flutuante (cada operação aritmética ou raiz produz um erro relativo \le u). Seja \text{abs}(x)=|x|.
  1. Calcule \text{absx}=\text{abs}(x).\n
  2. Se \text{absx}\le 1 (caso pequeno — evita cancelamento):
    • compute s=\operatorname{fl}(x\cdot x). (isto é \operatorname{fl}(x^2))
    • compute t_1=\operatorname{fl}(2\cdot s).
    • compute a=\operatorname{fl}(t_1+1). (representa 2x^2+1)
    • compute b=\operatorname{fl}(s+1). (representa x^2+1)
    • compute r_1=\operatorname{fl}(\sqrt{a}).
    • compute r_2=\operatorname{fl}(\sqrt{b}).
    • compute \text{den}=\operatorname{fl}(r_1+r_2).
    • compute \widetilde{f}=\operatorname{fl}(s/\text{den}).
    • devolver \widetilde{f}.
  3. Se \text{absx}>1 (caso moderado/grande — evita overflow do termo x^2 e mantém boa precisão):
    • compute y=\operatorname{fl}(1/\text{absx}).
    • compute y2=\operatorname{fl}(y\cdot y). (isto é 1/x^2)
    • compute A=\operatorname{fl}(2+y2).
    • compute B=\operatorname{fl}(1+y2).
    • compute r_1=\operatorname{fl}(\sqrt{A}).
    • compute r_2=\operatorname{fl}(\sqrt{B}).
    • compute \text{diff}=\operatorname{fl}(r_1-r_2).
    • compute \widetilde{f}=\operatorname{fl}(\text{absx}\cdot \text{diff}).
    • devolver \widetilde{f}.
Observações sobre os ramos:
  • No ramo 2 (pequeno), uso a forma racionalizada \dfrac{x^2}{\sqrt{2x^2+1}+\sqrt{x^2+1}}, que evita subtração de duas raízes quase iguais.
  • No ramo 3 (grande), fatorizei |x| para evitar cálculo direto de x^2 que poderia overflow: usando f(x)=|x|\big(\sqrt{2+1/x^2}-\sqrt{1+1/x^2}\big). Para x grande isso dá diferença de ordem |x|(\sqrt{2}-1), sem cancelamento.
  • Em implementações reais escolha o limiar (aqui usei 1) de acordo com formato (por exemplo em double pode ser diferente); o princípio é ter um critério que distingue “pequeno” (onde x^2 é muito menor que 1) de “grande” (onde x^2 pode causar overflow).

Passo 5

Análise rápida do erro (por que a ordem do erro final é O(u)) — argumento heurístico e compreensível:
  • Modelo de arredondamento: cada operação elementar (multiplicação, adição, raiz) devolve o valor exato multiplicado por (1+\delta) com |\delta|\le u.
  • No ramo pequeno, as quantidades intermediárias são: s=x^2 calculado com erro relativo \le u; a=2s+1 e b=s+1 têm erros relativos \le u; as raízes r_1=\sqrt{a}, r_2=\sqrt{b} têm erro relativo \le u; a soma \text{den}=r_1+r_2 tem erro absoluto \le u|r_1+r_2|. Como \text{den} é do mesmo tamanho de ordem 1 quando x é pequeno, seu erro relativo também é O(u). O quociente s/\text{den} junta erros relativos de numerador e denominador, resultando num erro relativo final que é uma soma de algumas constantes vezes u. Em primeira ordem (desprezando termos u^2), obtemos \displaystyle \frac{\widetilde{f}-f}{f}=O(u).
  • No ramo grande, calculamos y=1/|x| e depois raízes de 2+y^2 e 1+y^2; aí y^2 é pequeno, as operações são bem condicionadas e o produto final por |x| introduz apenas um fator de arredondamento adicional. Novamente a acumulação de erros é uma soma de poucos termos do tipo \delta_i com |\delta_i|\le u, logo o erro relativo final é O(u).
  • Em suma: cada passo é numericamente estável (não há divisão por quantidades muito menores que a magnitude dos operandos), e o número de operações é pequeno; assim o erro relativo final fica limitado por uma pequena constante vezes u. Isso satisfaz o requisito “erro relativo da ordem do erro da representação”.

Passo 6

Casos extremos e recomendações práticas:
  • Se houver risco de overflow em \text{absx} (por exemplo \text{absx}>\sqrt{\text{overflow\_threshold}}), use aritmética estendida / escala (dividir x por um fator de potência de 2, calcular e remultiplicar) ou detecte e trate overflow separadamente. O algoritmo acima evita a maior parte dos problemas porque no ramo grande eu trabalho com 1/\text{absx}.
  • Em implementações reais, prefira usar as funções de biblioteca (por exemplo, multiplicação, soma, sqrt) e verificar se \text{absx} está em intervalos seguros; escolha limiares testados para o tipo de ponto flutuante (single/double/long double).
  • Teste o algoritmo em valores de x muito pequenos (por exemplo x\approx 10^{-8} em double) e muito grandes para confirmar estabilidade e ausência de overflow.

Resposta

Se \text{abs}(x)\le 1: calcular
s=\operatorname{fl}(x\cdot x),\quad a=\operatorname{fl}(2s+1),\quad b=\operatorname{fl}(s+1),
\widetilde{f}=\operatorname{fl}\!\left(\dfrac{s}{\operatorname{fl}(\sqrt{a})+\operatorname{fl}(\sqrt{b})}\right).
Se \text{abs}(x)>1: calcular
y=\operatorname{fl}\!\left(\dfrac{1}{\text{abs}(x)}\right),\quad y2=\operatorname{fl}(y\cdot y),
\widetilde{f}=\operatorname{fl}\!\big(\text{abs}(x)\cdot\operatorname{fl}(\sqrt{\operatorname{fl}(2+y2)}-\sqrt{\operatorname{fl}(1+y2)})\big).
Este algoritmo evita cancelamento e overflow na prática; o erro relativo final é O(u) (ordem do erro de representação).

Exercícios relacionados