Currency e erro de arredondamento

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
mhackervix
Usuário Nível 3
Usuário Nível 3
Mensagens: 105
Registrado em: 11 Fev 2008 02:06
Localização: ES

Currency e erro de arredondamento

Mensagem 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?
Mhackervix, Msc.
Avatar do usuário
Mario Mesquita
Usuário Nível 4
Usuário Nível 4
Mensagens: 613
Registrado em: 08 Dez 2009 13:47
Localização: Rio de Janeiro

Currency e erro de arredondamento

Mensagem 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.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
mhackervix
Usuário Nível 3
Usuário Nível 3
Mensagens: 105
Registrado em: 11 Fev 2008 02:06
Localização: ES

Currency e erro de arredondamento

Mensagem 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.
Mhackervix, Msc.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
mhackervix
Usuário Nível 3
Usuário Nível 3
Mensagens: 105
Registrado em: 11 Fev 2008 02:06
Localização: ES

Currency e erro de arredondamento

Mensagem 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).
Mhackervix, Msc.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
mhackervix
Usuário Nível 3
Usuário Nível 3
Mensagens: 105
Registrado em: 11 Fev 2008 02:06
Localização: ES

Currency e erro de arredondamento

Mensagem 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".
Mhackervix, Msc.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Currency e erro de arredondamento

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
mhackervix
Usuário Nível 3
Usuário Nível 3
Mensagens: 105
Registrado em: 11 Fev 2008 02:06
Localização: ES

Currency e erro de arredondamento

Mensagem 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.
Mhackervix, Msc.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Currency e erro de arredondamento

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Responder