erro ao SOMAR valores
Moderador: Moderadores
erro ao SOMAR valores
Olá a todos,
Gostaria da ajuda dos amigos, pois não sei o que estou fazendo de errado no código abaixo:
DO WHILE .T.
set date british
cls
nSOMA = 0
vQTDPAR = 3
vVALDOC = 9.60
lin = 11
vVAL = 0
vDATVEM = DATE()
PARCELAS := {}
@ 05,30 SAY "Valor para teste" + STR(vVALDOC)
@ 06,30 SAY "Quantidade de Parcelas" get vQTDPAR Pict "9"
@ 07,30 SAY "1o. Vencimento" GET vDATVEM
READ
IF LASTKEY() = 27
EXIT
ENDIF
For i=1 to vQTDPAR
AADD(parcelas, {vVAL, i, vDATVEM})
vDATVEM = vDATVEM + 30
Next
For i=1 to vQTDPAR
@ lin,41 say parcelas[i,2] Pict "99"
@ lin,45 get parcelas[i,3]
@ lin,56 get parcelas[i,1] pict "@E 99,999.99"
lin := lin + 1
Next
read
For i=1 to vQTDPAR
nSOMA += parcelas[i,1]
Next
DO CASE
CASE nSOMA = vVALDOC
ALERT("** BLZ. FUNCIONOU **")
LOOP
CASE nSOMA <> vVALDOC
ALERT("VALOR DAS PARCELAS NAO BATE COM O VALOR TOTAL")
LOOP
ENDCASE
ENDDO
O problema é que quando o número de parcelas é 3, por mais que os valores das parcelas estejam certos, ele diz que a SOMA não bate. Neste exemplo usei o valor de R$ 9,60 (pode ser qualquer outro valor) dividido por 3 é R$ 3,20, mas dá o erro.
O mais interessante é que quando o número de parcelas é 1, 2, 4, 5..., o sistema soma direitinho, confere se o valor das parcelas bate com o valor do Documento e blz. Mas se for divido por 3 (e somente quando é por 3), babau.
Sinceramente eu não sei o que está acontecendo.
Alguém pode me dizer o que estou fazendo de errado?
Obrigado
Janio
Gostaria da ajuda dos amigos, pois não sei o que estou fazendo de errado no código abaixo:
DO WHILE .T.
set date british
cls
nSOMA = 0
vQTDPAR = 3
vVALDOC = 9.60
lin = 11
vVAL = 0
vDATVEM = DATE()
PARCELAS := {}
@ 05,30 SAY "Valor para teste" + STR(vVALDOC)
@ 06,30 SAY "Quantidade de Parcelas" get vQTDPAR Pict "9"
@ 07,30 SAY "1o. Vencimento" GET vDATVEM
READ
IF LASTKEY() = 27
EXIT
ENDIF
For i=1 to vQTDPAR
AADD(parcelas, {vVAL, i, vDATVEM})
vDATVEM = vDATVEM + 30
Next
For i=1 to vQTDPAR
@ lin,41 say parcelas[i,2] Pict "99"
@ lin,45 get parcelas[i,3]
@ lin,56 get parcelas[i,1] pict "@E 99,999.99"
lin := lin + 1
Next
read
For i=1 to vQTDPAR
nSOMA += parcelas[i,1]
Next
DO CASE
CASE nSOMA = vVALDOC
ALERT("** BLZ. FUNCIONOU **")
LOOP
CASE nSOMA <> vVALDOC
ALERT("VALOR DAS PARCELAS NAO BATE COM O VALOR TOTAL")
LOOP
ENDCASE
ENDDO
O problema é que quando o número de parcelas é 3, por mais que os valores das parcelas estejam certos, ele diz que a SOMA não bate. Neste exemplo usei o valor de R$ 9,60 (pode ser qualquer outro valor) dividido por 3 é R$ 3,20, mas dá o erro.
O mais interessante é que quando o número de parcelas é 1, 2, 4, 5..., o sistema soma direitinho, confere se o valor das parcelas bate com o valor do Documento e blz. Mas se for divido por 3 (e somente quando é por 3), babau.
Sinceramente eu não sei o que está acontecendo.
Alguém pode me dizer o que estou fazendo de errado?
Obrigado
Janio
-
gransoft
- Usuário Nível 3

- Mensagens: 321
- Registrado em: 06 Jul 2004 17:48
- Localização: UBERLÂNDIA-MG
- Contato:
Comparar números Reais
ARAGUARI-MG, 27 de agosto de 2004.
Prezado Janio,
Segue uma sugestão:
Ao comparar dois números reais, utilize a função:
Verifique no SEU algorítmo:
Atenciosamente,
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br
Prezado Janio,
Segue uma sugestão:
Ao comparar dois números reais, utilize a função:
Código: Selecionar todos
*** PROCEDURE para Comparar duas variaveis numericas ***
FUNCTION Compara(nValor1,nValor2) && COMPARA VALORES REAIS ...
IF VAL(STR(nValor1)) == VAL(STR(nValor2))
RETURN(.T.) && OK ...
ELSE
RETURN(.F.) && PROBLEMAS ...
END
***
Código: Selecionar todos
set date british
SET CENTURY ON
DO WHILE .T.
cls
nSOMA = 0
vQTDPAR = 3
vVALDOC = 9.60
lin = 11
vVAL = 0
vDATVEM = DATE()
PARCELAS := {}
@ 05,30 SAY "Valor para teste" + STR(vVALDOC)
@ 06,30 SAY "Quantidade de Parcelas" get vQTDPAR Pict "9"
@ 07,30 SAY "1o. Vencimento" GET vDATVEM
READ
IF LASTKEY() = 27
EXIT
ENDIF
For i=1 to vQTDPAR
AADD(parcelas, {vVAL, i, vDATVEM})
vDATVEM = vDATVEM + 30
Next
For i=1 to vQTDPAR
@ lin,41 say parcelas[i,2] Pict "99"
@ lin,45 get parcelas[i,3]
@ lin,56 get parcelas[i,1] pict "@E 99,999.99"
READ
lin := lin + 1
Next
For i=1 to vQTDPAR
nSOMA += parcelas[i,1]
Next
DO CASE
* CASE nSOMA = vVALDOC
CASE Compara(nSOMA,vVALDOC)
? "** BLZ. FUNCIONOU **"
INKEY(0)
LOOP
OTHERWISE // CASE Compara(nSOMA,vVALDOC)
?"VALOR DAS PARCELAS NAO BATE COM O VALOR TOTAL"
INKEY(0)
LOOP
ENDCASE
ENDDO
***
*** PROCEDURE para Comparar duas variaveis numericas ***
FUNCTION Compara(nValor1,nValor2) && COMPARA VALORES REAIS ...
IF VAL(STR(nValor1)) == VAL(STR(nValor2))
RETURN(.T.) && OK ...
ELSE
RETURN(.F.) && PROBLEMAS ...
END
***
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br
-
gransoft
- Usuário Nível 3

- Mensagens: 321
- Registrado em: 06 Jul 2004 17:48
- Localização: UBERLÂNDIA-MG
- Contato:
Comparar números Reais...
ARAGUARI-MG, 27 de agosto de 2004.
Prezado Janio,
Complementando, inclua essas linhas e veja o problema:
Atenciosamente,
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br
Prezado Janio,
Complementando, inclua essas linhas e veja o problema:
Código: Selecionar todos
? "** BLZ. FUNCIONOU **"
? TRANSFORM(nSOMA, '@E 9,999.9999999999999999') + SPACE(01) + ;
TRANSFORM(vVALDOC,'@E 9,999.9999999999999999')
INKEY(0)
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br
A comparação de dois números em ponto flutuante às vezes produz esse tipo de problema. Isso não é só privilégio do Clipper, mas de qualquer linguagem que internamente armazene números nesse padrão. Para resolver isso, criei uma função que transforma os valores e compara suas strings. Acho mais confiável que comparar números normalizados.
Fica, portanto, minha contribuição para a solução do seu problema.
[]'s
Maligno
http://www.buzinello.com/prg
Código: Selecionar todos
function CompNum(v1,v2,nDec)
default nDec to 2
return Str(v1*(10**nDec),18) == Str(v2*(10**nDec),18)[]'s
Maligno
http://www.buzinello.com/prg
A comparação de dois números em ponto flutuante às vezes produz esse tipo de problema. Isso não é só privilégio do Clipper, mas de qualquer linguagem que internamente armazene números nesse padrão. Para resolver isso, criei uma função que transforma os valores e compara suas strings. Acho mais confiável que comparar números normalizados.
Fica, portanto, minha contribuição para a solução do seu problema.
[]'s
Maligno
http://www.buzinello.com/prg
Código: Selecionar todos
function CompNum(v1,v2,nDec)
default nDec to 2
return Str(v1*(10**nDec),18) == Str(v2*(10**nDec),18)[]'s
Maligno
http://www.buzinello.com/prg
-
gransoft
- Usuário Nível 3

- Mensagens: 321
- Registrado em: 06 Jul 2004 17:48
- Localização: UBERLÂNDIA-MG
- Contato:
Parcelas...
ARAGUARI-MG, 30 de agosto de 2004.Marcos escreveu:Achei interessante o exemplo do Janis Peters, só que eu não consegui faze-lo funcionar, pois os campos onde é informado os valores já parcelados aparecem zerados.
Marcos
Prezado Marcos,
O exemplo é do amigo Janio, e ele deixou as parcelas zeradas de propósito. Informe no Total R$ 9,60 e nas três parcelas, R$ 3,20... dá erro sem a referida função, pois láaaaaa... na 15. casa decimal, o valor não é zero...
Atenciosamente,
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br
-
MARINI
- Usuário Nível 3

- Mensagens: 288
- Registrado em: 06 Jul 2004 08:06
- Localização: Pindamonhangaba SP
Re: erro ao SOMAR valores
Outra solução é usar o ROUND():janio escreveu:
O problema é que quando o número de parcelas é 3, por mais que os valores das parcelas estejam certos, ele diz que a SOMA não bate. Neste exemplo usei o valor de R$ 9,60 (pode ser qualquer outro valor) dividido por 3 é R$ 3,20, mas dá o erro.
http://www.clipx.net/ng/53guide/ng97783.php
No exemplo postado o valor 9.60 é divisível por 3, mas se
for 9.61 a soma não irá conferir.
Será necessário corrigir uma das parcelas com a diferença,
que no caso poderá ser a primeira parcela.
Para melhor esclarecer segue exemplo que poderá ser
testado com qualquer valor.
vr:=0.00
nparc:=1
venc:=DATE()
@ 1,5 say "VALOR......." get vr
@ 2,5 say "PARCELAS." get nparc
@ 3,5 say "1. VENC....." get venc
read
vrparc:={}
soma:=0
for i:=1 to nparc
//acha venc,,vr parcelas
AADD(vrparc,{venc+((i-1)*30),i,ROUND(vr/nparc,2)})
//soma vr parcelas
soma+=ROUND(vr/nparc,2)
next
//corrige na primeira parcerla eventual diferença
vrparc[1,3]:=vrparc[1,3]+vr-soma
soma:=0
for i:=1 to nparc
//confere vr parcelas
soma+=vrparc[i,3]
next
for i:=1 to nparc
@ i,40 say str(i)
@ i,53 say vrparc[i,3]
@ i,68 say vrparc[i,1]
next
//round = arredonda p/2 casa decimal ignorando nr flutuantes
if round(soma,2)=round(vr,2)
@ 22,5 say "total ok"
else
@ 22,5 say "total errado"
endif
Sds
Marini
Marini
Olá a todos e obrigado mais uma vez por responderem.
Marcos, concordo perfeitamente com o amigo Gransoft. Para o meu caso, os exemplos acima funcionaram e resolveram o meu problema. Na realidade os valores foram colocados ZERADOS somente para um teste, para não correr o risco de ter valores quebrados. Mas se vc quer que já saia o valor de cada parcela basta dividir o VALOR DO DOCUMENTO pelo Nº DE PARCELAS, e alterar o código acima neste ponto:
For i=1 to vQTDPAR
AADD(parcelas, {(vVALDOC/vQTDPAR), i, vDATVEM})
vDATVEM = vDATVEM + 30
Next
Marani,
Valeu! Quando a divisão não é exata, eis que surgiria esse outro problema, mas com a sua ajuda, solucionado!
Maligno,
Até que enfim reapareceu, né?
Bay, Bay
Jânio
Marcos, concordo perfeitamente com o amigo Gransoft. Para o meu caso, os exemplos acima funcionaram e resolveram o meu problema. Na realidade os valores foram colocados ZERADOS somente para um teste, para não correr o risco de ter valores quebrados. Mas se vc quer que já saia o valor de cada parcela basta dividir o VALOR DO DOCUMENTO pelo Nº DE PARCELAS, e alterar o código acima neste ponto:
For i=1 to vQTDPAR
AADD(parcelas, {(vVALDOC/vQTDPAR), i, vDATVEM})
vDATVEM = vDATVEM + 30
Next
Marani,
Valeu! Quando a divisão não é exata, eis que surgiria esse outro problema, mas com a sua ajuda, solucionado!
Maligno,
Até que enfim reapareceu, né?
Bay, Bay
Jânio
Editado pela última vez por janio em 31 Ago 2004 08:46, em um total de 1 vez.
- Marcos
- Usuário Nível 3

- Mensagens: 355
- Registrado em: 20 Set 2003 09:16
- Localização: Cáceres/Mato Grosso
Editar as Parcelas.
Janio, obrigado pela ajuda, gostaria de saber se há a possibilidade de alterar o valor e a data das parcelas.
Marcos
Marcos
Olá Marcos,
dá pra fazer, basta alterar nestes pontos:
DO WHILE .T.
set date british
cls
nSOMA = 0
vQTDPAR = 3
vVALDOC = 0
lin = 11
vVAL = 0
vDATVEM = CTOD(" ")
PARCELAS := {}
@ 05,30 SAY "Valor para teste" GET vVALDOC PICT "@E 99,999.99"
@ 06,30 SAY "Quantidade de Parcelas" get vQTDPAR Pict "9"
@ 07,30 SAY "1o. Vencimento" GET vDATVEM
READ
IF LASTKEY() = 27
EXIT
ENDIF
For i=1 to vQTDPAR
AADD(parcelas, {(vVALDOC/vQTDPAR), i, vDATVEM})
Next
...
Janio
dá pra fazer, basta alterar nestes pontos:
DO WHILE .T.
set date british
cls
nSOMA = 0
vQTDPAR = 3
vVALDOC = 0
lin = 11
vVAL = 0
vDATVEM = CTOD(" ")
PARCELAS := {}
@ 05,30 SAY "Valor para teste" GET vVALDOC PICT "@E 99,999.99"
@ 06,30 SAY "Quantidade de Parcelas" get vQTDPAR Pict "9"
@ 07,30 SAY "1o. Vencimento" GET vDATVEM
READ
IF LASTKEY() = 27
EXIT
ENDIF
For i=1 to vQTDPAR
AADD(parcelas, {(vVALDOC/vQTDPAR), i, vDATVEM})
Next
...
Janio
- Marcos
- Usuário Nível 3

- Mensagens: 355
- Registrado em: 20 Set 2003 09:16
- Localização: Cáceres/Mato Grosso
Editar as Parcelas.
Janio desculpe-me acho que expressei mal, eu queria dizer Alterar o valor e Vencimento das parcelas, ou seja, após informar a Qtd de Parcelas, a função dividira o valor pela qtd de parcelas, após isto eu queria uma opção para alterar os valores das parcelas juntamente com a data de vencimento das mesmas c necessário.
Marcos
Marcos
- Augusto
- Usuário Nível 3

- Mensagens: 473
- Registrado em: 26 Ago 2003 17:50
- Localização: Maricá/RJ
- Contato:
Embora me pareça que o problema do colega esteja resolvido, uma outra idéia é dividir o valor pela quantidade de parcelas e multiplicá-las pela mesma quantidade - 1 e em seguida subtrair do valor original do valor encontrado por essa multiplicação o que me daria o valor da última prestação...
Ex:
vParc = vOrig / qParc
vTemp = vParc * (qParc-1)
vUltParc = vOrig - vTemp
Dessa forma não é necessário se preocupar com arredondamentos ou se o vOrig é divisível pela qParc sem deixar restos...
Ex:
vParc = vOrig / qParc
vTemp = vParc * (qParc-1)
vUltParc = vOrig - vTemp
Dessa forma não é necessário se preocupar com arredondamentos ou se o vOrig é divisível pela qParc sem deixar restos...
:xau Fui...
goulart@provsul.com.br
Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
goulart@provsul.com.br
Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
-
gransoft
- Usuário Nível 3

- Mensagens: 321
- Registrado em: 06 Jul 2004 17:48
- Localização: UBERLÂNDIA-MG
- Contato:
Bombaxa e chimarrão...
ARAGUARI-MG, 1. de setembro de 2004.
Prezado Augusto,
Simples e boa a idéia... você estava meio sumido.
Mas ... báh tchê!!! Bombaxa e chimarrão no esqueleto ao lado?
Só falta agora filiar-te também ao grupo xHarbour ... Uai tchê !
Atenciosamente,
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br
Prezado Augusto,
Simples e boa a idéia... você estava meio sumido.
Mas ... báh tchê!!! Bombaxa e chimarrão no esqueleto ao lado?
Só falta agora filiar-te também ao grupo xHarbour ... Uai tchê !
Atenciosamente,
Janis Peters Grants.
http://www.gransoft.com.br
gransoft@zipmail.com.br

