GARANTIR DESCONTO

Fórum Firebird e valores monetários #53382

17/10/2005

0

Já li vários textos à respeito do assunto e ainda tenho dúvidas. Até agora sempre usei DOUBLE PRECISION no IB/FB para simular campos monetários, mas já ouvi falar que é melhor NUMERIC/DECIMAL para evitar certos problemas de precisão mas tb dizem que nem esse tipo de campo está totalmente livre de problemas de arredondamento e que em alguns casos o tipo de dupla precisão ainda é melhor. Por isso, gostaria que os colegas do fórum opinassem a respeito, dizendo que tipo de dados usam para simular valores monetários (no caso do NUMERIC/DECIMAL indiquem a precisão tb), se tem algum problema de compatibilidade com o tipo Currency do Delphi, problemas de arredondamento, esse tipo de coisa.


Gandalf.nho

Gandalf.nho

Responder

Posts

17/10/2005

Vinicius2k

Eu nunca tive problemas com DOUBLE PRECISION porque sempre usei NUMERIC e, com este, nunca tive problemas.

Quando possível, eu utilizo no máximo NUMERIC(9,e) para que o IB/FB utilize o tipo INTEGER para armazenar o dado, economizando (eu acho) tamanho do registro, já que a partir de NUMERIC(10,e) ele irá utilizar INT64 internamente.

Nunca tive problemas de arredondamento e de incompatibilidade, apesar de TFmtBCD ter me dado ´algum trabalho´ no início (com dbExpress).

Creio que muitas vezes os problemas com DOUBLE e NUMERIC podem ser evitados. Por exemplo, na aplicação, eu nunca faço CAMPO_1 := CAMPO_2 * CAMPO_3. Eu procuro já tratar o arredondamento correto dentro da aplicação. Algo como: CAMPO_1 := ROUND(CAMPO_2 * CAMPO_3, 2), fazendo com que o campo já receba o valor da forma correta.

Se vc também utiliza esta prática, pode ser esta a razão de nunca ter tido problemas com DOUBLE, já que todos reclamam, deve mesmo ser ruim sem o tratamento adequado.

T+


Responder

Gostei + 0

17/10/2005

Afarias

como pode ser visto no post abaixo:

http://forum.clubedelphi.net/viewtopic.php?t=69062&highlight=float

Tipos de ponto-flutuante são um ´problema´ em geral para a computação, não importa o banco de dados, sistema operacional ou o q for.

Tipos como FLOAT ([url=http://www.math.grin.edu/~stone/courses/fundamentals/IEEE-reals.html]IEEE[/url] single precision: 7 dígitos) ou DOUBLE PRECISION (IEEE double precision: 15 dígitos) são por natureza ´imprecisos´.

Para valores monetários e outros situações q exigem precisão (e geralmente poucas casas decimais) diversas soluções são abordadas como a adoção de tipos inteiros ou [url=http://en.wikipedia.org/wiki/Binary-coded_decimal]BCDs[/url] para representar valores de ponto-flutuante

No Interbase/Firebird, os ´tipos´ NUMERIC/DECIMAL não representam TIPOS reais mas apenas uma dessas soluções mencionadas acima.

O IB/FB determina a [melhor] forma de armazenamento do NUMERIC dependendo da precisão (´tamanho máximo´) do valor e do dialeto da base.

Para bancos no dialeto1 uma precisão até 9 é suportada como INTEGER internamente, provendo valores representados perfeitamente. Já no Dialeto 3, com o ´advento´ do INT64, é suportado até uma precisão de 18

É uma boa prática *sempre* usar NUMERIC, a não ser q realmente seja desejado/necessário um campo de ponto-flutuante (FLOAT ou DOUBLE)


T+


Responder

Gostei + 0

17/10/2005

Afarias

Ah, e quanto ao Currency do Delphi, é mais uma solução dessas ... o Currency serve para representar valores de campos flutuante (até 4 casas decimais) mas é um INTEIRO

(Obs: o Delphi não implementa um tipo BCD, até onde sei)


T+


Responder

Gostei + 0

18/10/2005

Gandalf.nho

E qual precisão devo usar? Alguns falam em (18,2), outros em (14,2) ou (9,2). A maioria dos meus cálculos envolvendo valores monetários geralmente são simples somas ou subtrações, raramente preciso trabalhar com divisão ou multiplicação. Dá para converter sem problema um campo DOUBLE PRECISION (já populado) para NUMERIC/DECIMAL?


Responder

Gostei + 0

18/10/2005

Afarias

|E qual precisão devo usar? Alguns falam em (18,2), outros em (14,2) ou
|(9,2).

Não existe uma precisão melhor q outra. No dialeto 1 o melhor é usar no máximo 9, já no dialeto 3 pode usar até 18.

Não tem fórmula aqui, use a maior precisão q acha q vai precisar. Exemplo: se para um determinado campo o valor máximo extrapolando tudo é 9 milhões, e ele é monetário (2 casas decimais) então vc usaria um campo NUMERIC(9,2) -- sendo assim: 9.999.999,99

(veja q esse número não é o máximo real, apenas o máximo admitindo a precisão e escala)


|Dá para converter sem problema um campo DOUBLE PRECISION (já
|populado) para NUMERIC/DECIMAL?

Se vc não tem problemas no uso de DOUBLE não acho q deve ficar preocupada em migrar o q já existe. Mas se for migrar, esteja atenta para ver se a conversão foi ok


T+


Responder

Gostei + 0

18/10/2005

Vinicius2k

(Obs: o Delphi não implementa um tipo BCD, até onde sei)

Anderson,
Não implementa mesmo ou vc acha que a implementação é ruim?

Pergunto pois, até onde eu sei, a partir do Delphi 6 a implementação já existe, inclusive utilizada no dbExpress. A unit da implementação é a ´FMTBcd´.

Não tem fórmula aqui, use a maior precisão q acha q vai precisar. Exemplo: se para um determinado campo o valor máximo extrapolando tudo é 9 milhões, e ele é monetário (2 casas decimais) então vc usaria um campo NUMERIC(9,2) -- sendo assim: 9.999.999,99

Concordo. Creio que a precisão escolhida não tem influência no resultado final de operações matemáticas porque o dado é armazenado como INTEGER. Acho que apenas seguir a regra ´básica´ de não criar campos maiores do que se precisa é suficiente. Como disse anteriomente, quando possível eu uso até NUMERIC(9,e) para que o IB/FB não precise utilizar INT64 para armazenar o dado. Mas se não for possível, de NUMERIC(10,e) em diante eu uso muitas variações, dependendo do caso.

T+


Responder

Gostei + 0

18/10/2005

Afarias

|Não implementa mesmo ou vc acha que a implementação é ruim?

Não implementa. Bom, mas pra ser mais exato ...

Não implementra um tipo BCD (Decimal) nativo!

O TBCD é um registro usado para representar um número BCD (vindo de um banco de dados por exemplo). O TBCDField por exemplo pega esse numero BCD e então transforma internamente em um Currency (Binário) para manipular (cálculos, etc) e converte novamente para a representação (TBCD) quando tem q enviar de volta para o banco.

É verdade q no D6 em diante (meu Delphi é o 5 ainda) há mais funções para trabalhar com TBCDs, mas ainda para isso (a melhor forma) é usar Variants.

Então, o fato é: O Delphi não possui um tipo BCD *nativo* :)

Para manipular números mesmo no código (cálculos e tals) vc tem/deve mesmo usar Currency

Valeu pela observação! Abraço


T+


Responder

Gostei + 0

18/10/2005

Gandalf.nho

Bem que o Firebird podia implementar um tipo monetário nativo, como outros bancos tem (até o Paradox e o Access tem...). Não sei como é em relação aos outros bancos cliente/servidor


Responder

Gostei + 0

18/10/2005

Afarias

|Bem que o Firebird podia implementar um tipo monetário nativo

Mas essa é a função do NUMERIC.

Não necessariamente tem q se usar um BCD, o q importa é o resultado não? Acho a solução de usar ponto-fixo (fixed-point decimals) muito boa.


T+


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar