Estou ciente de que a aritmética de ponto flutuante tem problemas de precisão. Normalmente, eu os supero alternando para uma representação decimal fixa do número ou simplesmente negligenciando o erro.
No entanto, não sei quais são as causas dessa imprecisão. Por que existem tantos problemas de arredondamento nos números flutuantes?
decimal
tipo do .NET funciona. O ponto fixo, por outro lado, é diferente. Contanto que seu alcance seja limitado, o ponto fixo é uma ótima resposta. Mas a faixa restritiva torna o ponto fixo inadequado para muitas aplicações matemáticas e, como resultado, as implementações de números de ponto fixo geralmente não são bem otimizadas em hardware.Respostas:
Isso ocorre porque algumas frações precisam de uma quantidade muito grande (ou mesmo infinita) de locais a serem expressos sem arredondamentos. Isso vale tanto para notação decimal quanto para binário ou qualquer outro. Se você limitar a quantidade de casas decimais a ser usada em seus cálculos (e evitar fazer cálculos em notação de fração), será necessário arredondar até uma expressão simples como 1/3 + 1/3. Em vez de escrever 2/3 como resultado, você teria que escrever 0,33333 + 0,33333 = 0,66666, que não é idêntico a 2/3.
No caso de um computador, o número de dígitos é limitado pela natureza técnica de seus registros de memória e CPU. A notação binária usada internamente adiciona mais algumas dificuldades. Os computadores normalmente não podem expressar números em notação de fração, embora algumas linguagens de programação adicionem essa capacidade, o que permite que esses problemas sejam evitados até certo ponto.
O que todo cientista da computação deve saber sobre aritmética de ponto flutuante
fonte
Principalmente, os erros de arredondamento vêm do fato de que o infinito de todos os números reais não pode ser representado pela memória finita de um computador , muito menos por uma pequena fatia de memória, como uma única variável de ponto flutuante , de modo que muitos números armazenados são apenas aproximações de o número que eles devem representar.
Como existe apenas um número limitado de valores que não são uma aproximação e qualquer operação entre uma aproximação e outro número resulta em uma aproximação, os erros de arredondamento são quase inevitáveis .
O importante é perceber quando eles podem causar um problema e tomar medidas para mitigar os riscos .
Além do essencial de David Goldberg , O que todo cientista da computação deve saber sobre aritmética de ponto flutuante (republicado pela Sun / Oracle como um apêndice ao Guia de computação numérica ), mencionado por thorsten , o periódico ACCU Overload teve um excelente série de artigos de Richard Harris sobre o Floating Point Blues .
A série começou com
Richard começa explicando a taxonomia de números reais, racionais, irracionais, algébricos e transcendentais. Ele então explica a representação da IEEE754, antes de passar para o erro de cancelamento e problemas de ordem de execução.
Se você não ler mais do que isso, terá uma excelente base nos problemas associados aos números de ponto flutuante.
Se você quiser saber mais, no entanto, ele continua com
Ele então muda para tentar ajudá-lo a curar seu Calculus Blues
e por último mas não menos importante, existe
Vale a pena examinar toda a série de artigos e, com 66 páginas no total, ainda são menores que as 77 páginas do artigo de Goldberg .
Embora esta série cubra muito do mesmo terreno, achei-a bastante mais acessível que o artigo de Goldberg . Também achei mais fácil entender as partes mais complexas do artigo depois de ler os artigos anteriores de Richards e, depois desses primeiros artigos, Richard ramifica-se em muitas áreas interessantes não abordadas pelo artigo de Goldberg.
Como assim falou ak mencionado nos comentários:
fonte
Bem, thorsten tem o link definitivo . Eu adicionaria:
Qualquer forma de representação terá algum erro de arredondamento para algum número. Tente expressar 1/3 no ponto flutuante IEEE ou decimal. Nem pode fazê-lo com precisão. Isso vai além da resposta à sua pergunta, mas usei essa regra prática com êxito:
fonte
O que parece não ter sido mencionado até agora são os conceitos de um algoritmo instável e um problema mal condicionado . Vou abordar o primeiro primeiro, pois isso parece ser uma armadilha mais frequente para numericistas novatos.
Considere o cálculo dos poderes da proporção áurea (recíproca)
φ=0.61803…
; Uma maneira possível de fazer isso é usar a fórmula de recursãoφ^n=φ^(n-2)-φ^(n-1)
, começando comφ^0=1
eφ^1=φ
. Se você executar essa recursão no seu ambiente de computação favorito e comparar os resultados com os poderes avaliados com precisão, encontrará uma erosão lenta de números significativos. Aqui está o que acontece, por exemplo, no Mathematica :O resultado pretendido para
φ^41
tem o sinal errado e, ainda mais cedo, os valores reais e calculados paraφ^39
compartilhar sem dígitos em comum (3.484899258054952
* ^ - 9for the computed version against the true value
7.071019424062048*^-9
). O algoritmo é, portanto, instável, e não se deve usar essa fórmula de recursão em aritmética inexata. Isso se deve à natureza inerente da fórmula de recursão: existe uma solução "decadente" e "crescente" para essa recursão, e tenta-se calcular a solução "decadente" por solução direta quando existe uma solução "crescente" alternativa que está implorando para sofrimento numérico. Portanto, deve-se garantir que seus algoritmos numéricos sejam estáveis.Agora, sobre o conceito de um problema mal condicionado : embora possa haver uma maneira estável de fazer algo numericamente, pode muito bem ser que o problema que você possui simplesmente não possa ser resolvido pelo seu algoritmo. Isso é culpa do problema em si, e não do método de solução. O exemplo canônico em numérica é a solução de equações lineares envolvendo a chamada "matriz de Hilbert":
A matriz é o exemplo canônico de uma matriz mal condicionada : tentar resolver um sistema com uma matriz Hilbert grande pode retornar uma solução imprecisa.
Aqui está uma demonstração do Mathematica : compare os resultados da aritmética exata
e aritmética inexata
(Se você testou no Mathematica , notará algumas mensagens de erro avisando sobre o mau condicionamento que aparece.)
Nos dois casos, simplesmente aumentar a precisão não é cura; apenas atrasará a inevitável erosão das figuras.
Isto é o que você pode enfrentar. As soluções podem ser difíceis: pela primeira vez, você volta à prancheta ou vasculha revistas / livros / o que quer que seja para descobrir se alguém encontrou uma solução melhor do que a sua; no segundo, você desiste ou reformula seu problema para algo mais tratável.
Vou deixar você com uma citação de Dianne O'Leary:
fonte
porque os números decimais da base 10 não podem ser expressos na base 2
ou, em outras palavras, 1/10 não pode ser transformado em uma fração com uma potência de 2 no denominador (que é essencialmente o que são os números de ponto flutuante)
fonte
9*3.3333333
em decimal e comapre9*3 1/3
.1 + .1 != .2
porque a codificação binária de ponto flutuante é usada, não decimal.1.0/3.0*3.0 != 1.0
, porque a codificação binária de ponto flutuante é usada, não trinária.Em matemática, existem infinitos números racionais. Uma variável de 32 bits pode ter apenas 2 32 valores diferentes e uma variável de 64 bits apenas 2 64 valores. Portanto, existem infinitos números racionais que não têm representação precisa.
Poderíamos criar esquemas que nos permitissem representar 1/3 perfeitamente, ou 1/100. Acontece que, para muitos propósitos práticos, isso não é muito útil. Há uma grande exceção: nas finanças, as frações decimais geralmente aparecem. Isso ocorre principalmente porque o financiamento é essencialmente uma atividade humana, não física.
Portanto, geralmente escolhemos usar ponto flutuante binário e arredondamos qualquer valor que não possa ser representado em binário. Mas, nas finanças, às vezes escolhemos o ponto flutuante decimal e arredondamos os valores para o valor decimal mais próximo.
fonte
"√2"
. (Minha antiga calculadora HP-48 foi capaz de fazer exatamente isso, e a quadratura desse valor resultou exatamente2.0
.) Há apenas uma infinidade contável de números reais representáveis para qualquer representação finita - mas nenhum cálculo pode produzir um número que não seja, em princípio, representável. Na prática, o ponto flutuante binário limita drasticamente o conjunto de números representáveis, com o benefício da velocidade impressionante e do armazenamento minúsculo em relação às representações simbólicas.o único "problema de arredondamento" realmente óbvio com números de ponto flutuante em que penso é nos filtros da média móvel:
$$ \ begin {align} y [n] e = \ frac {1} {N} \ sum \ limits_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align}
Para que isso funcione sem o acúmulo de ruído, você deve certificar-se de que o $ x [n] $ adicionado nas amostras atuais seja exatamente igual ao $ x [nN] $ que você subtrairá $ N $ amostras no futuro. se não for, o que é diferente é um pouco de cocô que fica preso na linha de atraso e nunca sai. isso ocorre porque esse filtro de média móvel é realmente construído com um IIR que possui um pólo marginalmente estável em $ z = 1 $ e um zero que o cancela por dentro. mas, é um integrador e qualquer porcaria que seja integrada e não totalmente removida existirá na soma do integrador para sempre. é aqui que o ponto fixo não tem o mesmo problema que os números de ponto flutuante.
fonte