Erros de arredondamento nos campos NUMERIC e DECIMAL (Firebird)


Atenção: O conteúdo desse artigo é válido para bases de dados criadas no InterBase em versões anteriores a 6.0, ou em bases de dados IB/FB que utilizam o dialeto 1. Em bases de dados com dialeto 3, tanto NUMERIC ou DECIMAL serão armazenados internamente como inteiros, garantindo a exatidão.


Problema :

O número armazenado nos campos NUMERIC ou DECIMAL tem mais casas decimais do que está especificado no parametro scale e/ou o número armazenado é uma aproximação do número que deveria estar armazenado.


Solução :


O que está sendo visto é o comportamento do formato IEEE utilizado para armazenar números nos campos NUMERIC ou DECIMAL. A definição do comportamento do formato IEEE é dada à seguir :
O número que resulta da leitura do formato IEEE que está armazenado nos campos NUMERIC ou DECIMAL produz um número que contém uma porção inteira de um número e uma parte decimal (ex: 3.141592, que é um pi estimado). As porções inteiras e decimais do números são representadas por padrões. O componente fracionado é computado adicionando-se os bits que representam a porção decimal do número. Os padrões de bits utilizados para os valores decimais são representados nas séries aritméticas mostradas abaixo :
1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 64 + 1/128 + . . .
Os elementos dessa série são somados para se aproximar à porção decimal do número. Por exemplo, para se aproximar do número 0.33333333 (a fração de 1/3) os seguintes valores seriam utilizados :

1/4   = 0.25
 + 1/16   = 0.3125
 + 1/64   = 0.328125
 + 1/256  = 0.33203125
 + 1/1024 = 0.3330078125
 + 1/4096 = 0.333251953125
 + . . .  = . . .
A maioria dos valores decimais são aproximados, os únicos valores que são exatamente calculados são aqueles que são somas dos elementos das séries de 1/2 + 1/4 + 1/8 + . . . que é dada acima.


Vantagens:

O formato IEEE é usado pelo coprocessador matemático para executar cálculos. Usar o coprocessador para executar operações matemáticas fornece uma performance superior doque utilizar bibliotecas matemáticas, como bibliotecas de ponto-flutuante ou BCD. Calculos envolvendo bibliotecas matemáticas são muito mais demorados.


Desvantagens:

Em situações onde a precisão na porção decimal do número é desejada (ex : aplicações financeiras) utilizar campos DECIMAL ou NUMERIC irão apresentar diversas situações que se deve ficar atento :
Erros de arredondamento: Quando executar operações como multiplicação e divisão com números IEEE, erros de arredondamento podem ocorrer. Para previnir que isso aconteça, o número pode ser convertido para BCD e a função matemática desejada será executada utilizando-se uma biblioteca BCD. As bibliotecas BCD podem ser utilizadas no lado do cliente ou através de UDFs em Stored Procedures ou Triggers. A BDE tem uma propriedade chamada EnableBCD que quando habilitada fará os cálculos BCD no lado do cliente para campos NUMERIC maiores que 4 posições ou campos DECIMAL.
Armazenando números no formato NUMERIC e DECIMAL : Enquanto bibliotecas BCD são utilizadas para fazer cálculos com precisão em se tratando da parte fracionada do número, após os cálculos, é importante definir onde o número será armazenado. Se o número for armazenado em uma coluna do tipo NUMERIC ou DECIMAL então ocorrerá aproximações devido ao formato IEEE. Para algumas aplicações isso pode ser aceitável, mas para outras não. Outros esquemas envolvem armazenar a porção inteira do número em uma coluna do tipo INTEGER e a porção fracionária em uma outra coluna do tipo INTEGER, e um outro esquema seria transformar o número em um STRING e armazena-lo em uma coluna do tipo CHAR ou VARCHAR.
Cometário :
O Interbase 6 suporta inteiros de até 64bits e automaticamente armazena os campos definidos até NUMERIC (18,2) em inteiros de 64bits de maneira à impedir que os erros de arredondamento aconteçam. Isso é transparente ao usuário. No Interbase 5.x, os números até NUMERIC (9,2) são armazenados em Inteiros de 32bits.
Deve-se tomar cuidado na conversão de um banco de dados da versão 5.x para a 6.0, pois os campos NUMERIC que já existirem continuarão sendo armazenados utilizando-se o formato IEEE.

Fonte do artigo original: Borland/Inprise

Nenhum comentário:

Postar um comentário