Página 1 de 1

Currency e erro de arredondamento

Enviado: 26 Out 2020 08:36
por mhackervix
Prezados Senhores,

Uma dificuldade que passamos é com relação ao tipo numérico no Harbour (e Xailer) quando se armazena valores de moeda. Quando existem muitos cálculos "fracionados" envolvendo estes podemos ter no final diferença de alguns centavos (tipo 0.01) além de conteúdos que imprimem "0.00" serem considerados diferentes de zero (tpo: if XX = 0).
No Delphi existe o tipo numérico "Currency" para se trabalhar com valores financeiros. Alguém conhece alguma boa ideia (solução) para esta questão?

Currency e erro de arredondamento

Enviado: 26 Out 2020 09:10
por Mario Mesquita
Bom dia a todos.

Eu converto o número para texto e depois volto para número para desprezar as dízimas que causam o arredondamento.

Para isso, converter com quatro casas decimais ou mais e tirar o substring até a segunda casa.

Saudações,
Mario.

Currency e erro de arredondamento

Enviado: 26 Out 2020 09:31
por Itamar M. Lins Jr.
Olá!
O DBF do Harbour tem CURRENCY.

? ROUND(valor,2)
? INT(&xPreco*100)/100

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 09:37
por mhackervix
Mario Mesquita escreveu:Bom dia a todos.

Eu converto o número para texto e depois volto para número para desprezar as dízimas que causam o arredondamento.

Para isso, converter com quatro casas decimais ou mais e tirar o substring até a segunda casa.

Saudações,
Mario.

Tenho feito desta forma também. Porém para uma linguagem de uso "comercial/financeira", poderia ter um tipo numérico para este fim.

Currency e erro de arredondamento

Enviado: 26 Out 2020 09:39
por Itamar M. Lins Jr.
Olá!
Para o comerciante é melhor usar round() com duas casas decimais. Pq até 1,504... fica 1,50 e 1,505... fica 1,51
Se não me engano. Abaixo de 5 ele despreza, e o comerciante não quer.

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 09:42
por Itamar M. Lins Jr.
Olá!
Eu entendo que o currency é um campo numérico com precisão de 4 decimais.

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 10:37
por mhackervix
Itamar M. Lins Jr. escreveu:Olá!
Para o comerciante é melhor usar round() com duas casas decimais. Pq até 1,504... fica 1,50 e 1,505... fica 1,51
Se não me engano. Abaixo de 5 ele despreza, e o comerciante não quer.

Saudações,
Itamar M. Lins Jr.
A soma de vários número com "arredondamento" (como em um cupom fiscal de supermercado com mais de 100 itens) muitas vezes não equivale ao total somado com arrendamento no final. O que nos obriga a fazermos "conversão" item a item durante a soma também (código de programação muito feio, mas eficaz).

Currency e erro de arredondamento

Enviado: 26 Out 2020 11:35
por Itamar M. Lins Jr.
Olá!
O que nos obriga a fazermos "conversão" item a item durante a soma também
Não entendi.
Estava com problema em campos com 3 digitos no decimal. M2/quilos.
Agora peguei outro problema no desconto proporcional.
O coeficiente gerado é por exemplo 0.000592.
7.284,31 - 4.31.
Distribuir 4.31 nos 14 itens proporcionalmente dá 4.34(somado depois) por conta dos valores de cada item.
A pessoa manda tirar 4.31 e o sistema tira 4.34.

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 12:40
por mhackervix
Como ainda não existe um tipo numérico próprio (seria interessante nas próximas versões do harbour), uma ideia é salvar os valores em centavos (multiplicar por 100), sendo este números inteiros. Evitando assim os erros nos ajustes de "aproximação".

Currency e erro de arredondamento

Enviado: 26 Out 2020 13:13
por Itamar M. Lins Jr.
Olá!
Matematicamente ainda não entendi a dificuldade do xBase e a vantagem do Delphi.
http://www.delphibasics.co.uk/RTL.asp?Name=Currency
Vi que é a mesma coisa no mundo xBase
var
account1, account2, account3 : Currency;
Será o mesmo no xBase

Código: Selecionar todos

function main
LOCAL account1, account2, account3
SET FIXED on
SET DECIMALS TO 4

? account1 := 123.456749
? account2 := 123.456750
? account3 := account1 + account2
inkey(0)
return nil

Código: Selecionar todos

C:\teste>hbrun decimais.prg                   
123.4567                                                                             
123.4568
246.9135        
O mesmo resultado. Ainda assim precisamos arredondar para 2 decimais usando round() ou truncando pq CURRENCY trabalha com 4 decimais e vai somar centavos no campo decimal.
Quando a variável é transformada em CURRENCY no PASCAL é a mesma coisa de usarmos round(account1,4)

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 13:47
por JoséQuintas
Já percebi que no MySQL também tem algo sobre isso.
Se gravar o campo como DOUBLE, ele está sujeito a diferenças, e como DECIMAL não, porque é gravado igual ao DBF.
Achei esquisito, mas tem essa também.

Currency e erro de arredondamento

Enviado: 26 Out 2020 14:48
por mhackervix
Itamar M. Lins Jr. escreveu:Olá!
Matematicamente ainda não entendi a dificuldade do xBase e a vantagem do Delphi.
http://www.delphibasics.co.uk/RTL.asp?Name=Currency
Vi que é a mesma coisa no mundo xBase
var
account1, account2, account3 : Currency;
Será o mesmo no xBase

Código: Selecionar todos

function main
LOCAL account1, account2, account3
SET FIXED on
SET DECIMALS TO 4

? account1 := 123.456749
? account2 := 123.456750
? account3 := account1 + account2
inkey(0)
return nil

Código: Selecionar todos

C:\teste>hbrun decimais.prg                   
123.4567                                                                             
123.4568
246.9135        
O mesmo resultado. Ainda assim precisamos arredondar para 2 decimais usando round() ou truncando pq CURRENCY trabalha com 4 decimais e vai somar centavos no campo decimal.
Quando a variável é transformada em CURRENCY no PASCAL é a mesma coisa de usarmos round(account1,4)

Saudações,
Itamar M. Lins Jr.
A questão não é comparar Delphi com harbour. A questão é que seria interessante um novo tipo numérico no harbour para suportar melhor favores monetários.


SET DECIMALS será aplicado a todas as variáveis numéricas e não somente as que "gostaríamos". No passado, usando CLIPPER SUMMER 87, tive que criar uma função INT, pois INT(X) do CLIPPER muitas vezes não "trazia" o valor igual a um inteiro para comparação (if). Como até hoje utilizo minha função, não sei se o harbour ainda tem este bug do CLIPPER.

É uma sujestão para os desenvolvedores do Harbour, dar uma ajustada no conjunto e tratamento das variáveis numéricas.

Currency e erro de arredondamento

Enviado: 26 Out 2020 17:37
por Itamar M. Lins Jr.
Olá!
A questão não é comparar Delphi com harbour. A questão é que seria interessante um novo tipo numérico no harbour para suportar melhor favores monetários.
Precisamos comparar para entender qual é o avanço.
Onde está o avanço ? Se temos que arredondar no Delphi ou no Harbour ?
Valores monetários do posto de gasolina tem 4 casas decimais, de cacau a arroba(15) quilos tem 6 decimais(dolar)
Acredito que 80% dos produtos de supermercado usamos 2 decimais, mas os produtos com peso já usamos 3 decimais.
Não vejo vantagem, em usar uma variável currency 4 decimais, se depois vou usar round(...,2), no Delphi ou no Harbour.

Com uma explicação usando códigos do Harbour ou do pascal compreenderei melhor.

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 17:44
por Itamar M. Lins Jr.
Olá!
Como até hoje utilizo minha função, não sei se o harbour ainda tem este bug do CLIPPER.
Essa é a questão. Cadê o teste ? Harbour não tem os bugs do clipper.
Fora por questões técnicas.(strict compatible) "-kc clear all flags (strict Clipper mode)"
if you want a 100% compatible runtime libraries then you have to define HB_CLP_STRICT, using HB_USER_CFLAGS=-DHB_CLP_STRICT, then rebuild.

Saudações,
Itamar M. Lins Jr.

Currency e erro de arredondamento

Enviado: 26 Out 2020 18:32
por Itamar M. Lins Jr.
Olá!
Lendo em outros foruns.
https://www.devmedia.com.br/forum/como- ... phi/324277
estive sempre acompanhando este tópico , ao longo deste calorosa discussão e sinceramente reprovo (no bom sentido é claro) esta idéia de tentar diminuir a precissão ....
Terceira mensagem de baixo para cima.
...
Qualquer que seja a opçaõ ´escolhida´ , no final dara sempre a diferençã de alguns centavos... e nessse caso voce so piora esta diferença na proporção INVERSA da PRECISÃO escolhida
Saudações,
Itamar M. Lins Jr.