Fórum Firebird e valores monetários #53382
17/10/2005
0
Gandalf.nho
Curtir tópico
+ 0Posts
17/10/2005
Vinicius2k
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+
Gostei + 0
17/10/2005
Afarias
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+
Gostei + 0
17/10/2005
Afarias
(Obs: o Delphi não implementa um tipo BCD, até onde sei)
T+
Gostei + 0
18/10/2005
Gandalf.nho
Gostei + 0
18/10/2005
Afarias
|(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+
Gostei + 0
18/10/2005
Vinicius2k
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´.
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+
Gostei + 0
18/10/2005
Afarias
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+
Gostei + 0
18/10/2005
Gandalf.nho
Gostei + 0
18/10/2005
Afarias
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+
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)