Problema con redondeo

Problema con redondeo

Postby informaticaeloy » Wed Jan 01, 2014 12:06 pm

Hola. Tengo un problema desde hace algún tiempo que no consigo depurar:
en mi programa de facturación, cuando hago una venta de 7€, guardo este total como 7,00€, pero la base imponible (calculando un 21% de iva) son 5,7851€. Si lo redondeo a 2 decimales, son 5,79€, y si lo redondeo a 2 decimales a la baja, son 5,78€, pero al volver a aplicarle el iva son 7,01€ o 6,99€, nunca los originales 7,00€. Realmente es solo 1 céntimo, pero no queda bien al hacer un ticket que ponga 5,79€ + iva = 7,01€ cuando realmente cobras 7€ y peor que salga 6,99€ y cobrar 7€. Uso la función round(nVALOR,2) en todo el proceso, en cada cálculo. Y si guardo más decimales, por ejemplo 5,7851€ con el iva son 6,999971€, que son los 7€, pero en la visualización de importes en factura no pueden aparecer esos decimales, solo 2.

No se por donde seguir. Ahora lo que hago es dejarlo con los 7,01€ y cobrar 7€, pero no queda profesional. ¿Alguna idea?

Feliz año 1110 para todos !!!
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby Daniel Garcia-Gil » Wed Jan 01, 2014 2:18 pm

Saludos

Prueba usar solo 2 decimales para la base imponible, agregar siempre 0.01 y usar solo los 2 primeros decimales del iva

ejemplo:

7/1.21 = 5.78 (solo los 2 primeros decimales) agregar 0.01 => 5.79

iva 21%

5.79 * 0.21 = 1.21 (solo los 2 primeros decimales)

5.79 + 1.21 = 7

otro ejemplo 17.37
17.37/1.21 = 14.35 + 0.01 => 14.36
14.36 * 0.21 = 3.01
14.36 + 3.01 = 17.37

otro ejemplo 13.53
13.53/1.21 = 11.18 + 0.01 => 11.19
11.19 * 0.21 = 2.34
11.19 + 2.34 = 13.53
User avatar
Daniel Garcia-Gil
 
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita

Re: Problema con redondeo

Postby informaticaeloy » Wed Jan 01, 2014 3:49 pm

ok. Probaré. Gracias. Un saludo.
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby Manuel Valdenebro » Wed Jan 01, 2014 4:38 pm

Te cuento como lo hago desde hace años:

1) Tengo una función en mi librería personal con el siguiente código:

//////////////////////////////////
/// evita errores en suma
/// al redondear al tercer decimal
//////////////////////////////////
FUNCTION ENTERO (nTotal)
nTotal := INT (nTotal*100)
nTotal := nTotal / 100
RETURN nTotal


2) Luego cuando lo aplico cuando lo necesito en una aplicación, normalmente con retenciones e IVA. Te pongo un ejemplo de código para que lo compruebes, usando los importe que tu indicas: total = 7 tipo iva = 21%

FUNCTION ELOY()
local nTotal, nIva, nNeto

// 1ª opcion cuando queremos calcular el IVA partiendo de un total

nIva := ROUND( ( 7 * 21 / 121 ), 2) // => 1,21

alert ( str( nIVA, 12, 6 ),, "IVA DESDE TOTAL" ) // => 1,21

nNeto := 7 - nIVA // 5,79

ALERT ( STR ( nNeto, 12, 6),,"NETO")

// Tambien podia haber hecho:

nNeto := ROUND( ( 7 / 1.21 ), 2)

ALERT ( STR ( nNeto, 12, 6),,"NETO")

// pero te aconsejo la resta porque siempr dará menos problemas.

// Hasta aqui todo normal pero al INVERTIR la operación, es cuando uso la función ENTERO()

nIva := ROUND( ENTERO ( nNeto * 0.21), 2 )

alert (str(nIVA, 12,6 ),,"IVA DESDE NETO")


// 2ª Opcion partiendo del neto de un artículo precio 5.79 calcular el IVA y el total

nIva := ROUND( ( ENTERO (5.79 * 0.21 )), 2)

alert ( str(nIVA, 12, 6 ),,"IVA CALCULADO DESDE NETO" )

nTotal := 5.79 + nIVA

ALERT ( STR ( nTotal, 12, 6),,"IMPORTE TOTAL")



RETURN nil



Feliz Año 2014 para todos.
Un saludo

Manuel
User avatar
Manuel Valdenebro
 
Posts: 706
Joined: Thu Oct 06, 2005 9:57 pm
Location: Málaga-España

Re: Problema con redondeo

Postby Daniel Garcia-Gil » Wed Jan 01, 2014 6:07 pm

Saludos

Te dejo el algoritmo que te comente al principio convertido a codigo

Code: Select all  Expand view

FUNCTION MAIN()

    Eloy()

RETURN NIL


FUNCTION Eloy()

    local nValor, nPorcentaje


    nPorcentaje = 21/100

    Calculos( 7, nPorcentaje )

    Calculos( 17.37, nPorcentaje )

    Calculos( 13.53, nPorcentaje )

    Calculos( 17, nPorcentaje )


RETURN NIL


FUNCTION Calculos( nValor, nPorcentaje )

    LOCAL nNeto, nIva, nTotal

    ? "Valor: ", nValor
    ? "Neto : ", nNeto := CalculoImponible( nValor, nPorcentaje )
    ? "Iva  : ", nIva := DosDecimales( nNeto * nPorcentaje )
    ? "Total: ", nTotal := nNeto + nIva
    ? "==========="

RETURN NIL

FUNCTION CalculoImponible( nValor, nPorcentaje )
RETURN AjusteParaIva( ( nValor / ( 1 + nPorcentaje ) ) )

FUNCTION AjusteParaIva( nValor )
RETURN DosDecimales( nValor ) + 0.01

FUNCTION DosDecimales( nTotal )
    nTotal = Int ( nTotal * 100 )
    nTotal = nTotal / 100
RETURN nTotal
 
User avatar
Daniel Garcia-Gil
 
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita

Re: Problema con redondeo

Postby informaticaeloy » Tue Jan 21, 2014 3:33 am

Manuel, llevo unos días con el tema del redondeo, y no me termina de funcionar. Lo hago con las ideas que me pasaste y funciona perfectamente con 7 y 9 €, pero con 8€ no termino de conseguirlo.

Lo explico sobre el código:
Code: Select all  Expand view

FUNCTION ELOY()
local nTotal, nIva, nNeto

// 1ª opcion cuando queremos calcular el IVA partiendo de un total

nIva := ROUND( ( 8 * 21 / 121 ), 2) // => 1,39

alert ( str( nIVA, 12, 6 ),, "IVA DESDE TOTAL" ) // => 1,39

nNeto := 7 - nIVA // 6,61

ALERT ( STR ( nNeto, 12, 6),,"NETO")

// Hasta aqui todo normal pero al INVERTIR la operación, es cuando uso la función ENTERO()

nIva := ROUND( ENTERO ( nNeto * 0.21), 2 ) => 1,3881 que al pasarlo a la función ENTERO se queda en 1,38 (ya no me sale el 1,39 de antes)

alert (str(nIVA, 12,6 ),,"IVA DESDE NETO")


// 2ª Opcion partiendo del neto de un artículo precio 6,61 calcular el IVA y el total

nIva := ROUND( ( ENTERO (6,61 * 0.21 )), 2) => 1,38

alert ( str(nIVA, 12, 6 ),,"IVA CALCULADO DESDE NETO" )

nTotal :=6,61 + nIVA => 7,99

ALERT ( STR ( nTotal, 12, 6),,"IMPORTE TOTAL")

RETURN nil

 


Con la opción de Daniel, si cambio los primeros valores a 7, 8 y 9€ y compilo, el resultado es el siguiente:
Valor 7
Neto 5.79
Iva 1.21
Total 7
==========
Valor 8
Neto 6.62
Iva 1.39
Total 8.01 ==>> distinto de valor inicial
==========
Valor 9
Neto 7.44
Iva 1.56
Total 9

Esta parte la necesito por que en mi programa de gestión, puedo meter ventas con el IVA incluído. Si hago una venta con iva incluido de 8€, en la parte de abajo del dialog tengo un browse con el desglose del iva en el que ya no se ve bien, que la venta sea de 8€, que la base sean 6.62 y que el importe de iva sean 1.39.

Hoy ya es tarde, que son las 4:45. Mañana probaré otra vez y os digo algo.
Un saludo. Gracias.
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby informaticaeloy » Tue Jan 21, 2014 4:42 am

Como no podía dormir, buscando un poquito por google encontré esto:
http://albertovilches.com/como-hacer-una-aplicacion-que-soporte-precios-con-decimales-sin-errores
A ver como lo hago en mi aplicación. Un saludo.
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby Manuel Valdenebro » Tue Jan 21, 2014 10:47 pm

Me imagino que tienes una tabla con los precios de los artículos. ¿Que precio es el que tu tienes en la tabla? ¿El Neto o el Total con el IVA incluido?.
Un saludo

Manuel
User avatar
Manuel Valdenebro
 
Posts: 706
Joined: Thu Oct 06, 2005 9:57 pm
Location: Málaga-España

Re: Problema con redondeo

Postby informaticaeloy » Tue Jan 21, 2014 11:38 pm

Hola. El problema es si quieres vender algo que no esta en la bd, sino que quieres vender un concepto a 8€. Me es imposible calcular una base y guardarla en la bd que al sumarle el 21% vuelva a ser 8€. Siempre sale o 7,9999... o 8,01 No se por donde tirar.

Gracias. Un saludo.
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby Willi Quintana » Wed Jan 22, 2014 1:19 am

Hola amigazo,,, prueba con esta función....
Salu2
Willi Quintana


*********************************************
Function FRound( x, y )
Local nDeci := 2 // error en el compilador
Default y := 2
nDeci := Set(3, y )
If x >= 0
x := Val( Str( Int( x * 10 ** y + 0.5000001 ) ) ) / 10 ** y
Else
x := Val( Str( Int( x * 10 ** y - 0.5000001 ) ) ) / 10 ** y
Endif
Set(3, nDeci ) // set decimal
Return(x)
User avatar
Willi Quintana
 
Posts: 1002
Joined: Sun Oct 09, 2005 10:41 pm
Location: Cusco - Perú

Re: Problema con redondeo

Postby cnavarro » Wed Jan 22, 2014 2:08 am

Eloy, esto me funciona perfectamente
Code: Select all  Expand view

   SET DECIMALS TO 2

   Msginfo( "Valor inicial : "+Str( 8.00, 5,2 ) + CRLF + ;
            "Base Imponible: "+Str( Round( 8/1.21 , 2 ) , 5 , 2 ) + CRLF + ;
            "IVA           : "+Str( Round(Round( 8/1.21 , 2 ) * 0.21,2) , 5 , 2 ) + CRLF + ;
            "Total         : "+Str( Round( 8/1.21 , 2 )+Round(Round( 8/1.21 , 2 ) * 0.21,2) , 5 , 2 ) ;
          )
 

Puedes indicar cual es la estructura del campo del fichero en el que guardas el valor calculado de la base Imponible?
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6500
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Problema con redondeo

Postby informaticaeloy » Fri Jan 24, 2014 12:51 am

Hola Cristobal,

la base de datos donde guardo los importes es n 15,6. He probado a guardar 2 decimales, 3, 4, 5 ... y si sale bien con 8€ falla con 7€ y si hago cambios en los redondeos con todos los códigos que me sugerís, si funciona con 7€ falla con 8€.


He probado con lo que me sugiere Willi Quintana y me pasa lo mismo.

Os explico exactamente lo que me sucede:

En el dialog de la edición de un artículo:
https://www.dropbox.com/s/x4ps25elfypae3w/ARTICULO.jpg

tengo un valid en el get del p.v.p. y otro en el de precio total. La idea es que si tengo que vender algo a 6,50€ + iva, lo escribo en el get del p.v.p. y el valid del p.v.p. me calcula el precio total, y si tengo que vender algo a 8€ con iva inlcuido, meto 8 en el get del precio total y el valid me calcula el p.v.p.

Ahora, con todas las sugerencias pasa lo siguiente:
según como lo implemento:
https://www.dropbox.com/s/x4ps25elfypae3w/ARTICULO.jpg
en este ejemplo de 8€ el valid del precio total me calcula un pvp de 6.61€ y el valid del pvp con 6.61€ me calcula un precio total de 8€

Si con esta misma implementación hago la prueba con 7€ el valid del precio total me calcula un pvp de 5.79€
https://www.dropbox.com/s/pi8yr6xifa1k04d/ARTICULO2.jpg
pero si me coloco sobre el get del pvp, y sin tocar los 5.79€ cambio de get para que actúe el valid, se calcula un precio total de
7.01€
https://www.dropbox.com/s/60hlplju2k5yf79/ARTICULO3.jpg

y realmente todavía no he guardado nada en la BD, es todo sobre variables hasta que le doy al botón de guardar.

No se ya si es matemáticamente imposible, pero he visto que el facturapluffff de sage lo calcula bien, y una demo de un compañero del foro, el Gestool 2Ktorce también, así que ando perdido, pero es muy feo tener que vender algo a 7 u 8€ y que a mi cliente le salga en los tickets de ventas 7,01€ o 8,01€.

Seguiré investigando, pero ya me está desesperando.
Esta semana he comprado por internet estos dos:
https://www.dropbox.com/s/4qcripekxsix499/clipper%205.2%20guia%20avanzada%20para%20el%20programador.jpg
y
https://www.dropbox.com/s/jsrp2mws0rcbf57/programacion%20en%20clipper%205.2%20rodriguez%20almeida.png

y estoy esperando a que me llegue este
https://www.dropbox.com/s/5qlg9ziviam60on/clipper%20tecnicas%20aplicaciones%20y%20rutinas%20de%20programaci%C3%B3n%20ra-ma.jpg
ya que aparte del problema este del redondeo no tenía nada de literatura de clipper.

Un saludo, gracias.
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby D.Fernandez » Fri Jan 24, 2014 1:28 pm

Hola Eloy:
A ver si con esta sale: La funcion xRound(), la pongo al final de estas lineas.

MsgInfo(xround( xROUND(7/1.21,3),2 ) )
MsgInfo(xRound( xROUND(7/1.21,3),2 ))
MsgInfo(xRound( xROUND(7/1.21,3),2 ) - 7 )

MsgInfo(xround( xROUND(8/1.21,3),2 ) )
MsgInfo(xRound( xROUND(8/1.21,3),2 ))
MsgInfo(xRound( xROUND(8/1.21,3),2 ) - 8 )

Aparentemente salen ok.

Function xRound( x, y )
Local nDeci := 2

y := 2

nDeci := Set( _SET_DECIMALS, y )
If x >= 0
x := Val( Str( Int( x * 10 ** y + 0.5000001 ) ) ) / 10 ** y
Else
x := Val( Str( Int( x * 10 ** y - 0.5000001 ) ) ) / 10 ** y
Endif
Set( _SET_DECIMALS, nDeci )

Return x


Saludos y espero que funcione.
Dario Fernandez
FWH 22.12, Harbour, MVS2022 Community, BCC, MySql & MariaDB, Dbf/Cdx VSCode.
Maldonado - Uruguay
D.Fernandez
 
Posts: 455
Joined: Wed Jul 31, 2013 1:14 pm
Location: Maldonado - Uruguay

Re: Problema con redondeo

Postby informaticaeloy » Sat Jan 25, 2014 12:03 am

Hola compañeros,

os informo, no funciona. He probado a hacer esto:

Code: Select all  Expand view

MSGALERT(XROUND(7/1.21,2))     //// sale 5.790000
MSGALERT(XROUND(8/1.21,2) )    //// sale 6.610000

MSGALERT(XROUND(5.790000*1.21,2))    //// sale 7.010000
MSGALERT(XROUND(6.610000*1.21,2) )    //// sale 8.000000

*********************************
Function xRound( x, y )
         Local nDeci := 2

         y := 2

         nDeci := Set( _SET_DECIMALS, y )
         If x >= 0
            x := Val( Str( Int( x * 10 ** y + 0.5000001 ) ) ) / 10 ** y
         Else
            x := Val( Str( Int( x * 10 ** y - 0.5000001 ) ) ) / 10 ** y
         Endif
         Set( _SET_DECIMALS, nDeci )

Return x
 


he encontrado por internet esta ayuda:
https://www.dropbox.com/s/09lxy65zhd2v2z3/redondeo.png
donde sugiere hacer redondeos a la alza o a la baja dependiendo de si la parte a discriminar se par o impar.

pero por no liarme y que funcione rápidamente, ya no tengo mucho tiempo antes de SEPA para terminar ciertas cosas, he optado por la siguiente opción:

- si quiero vender un artículo a 7€ de precio final, calculo su iva 7-(7/1.21) => 1.21€ y para calcular el precio sin iva hago 7-iva => 5.79€. En la ficha de artículo, guardo un campo indicando que el precio "bueno" es el precio final, y así cuando recalculo precios o intento calcularlos desde otra parte del programa, tengo el precio final del campo de la base de datos (7€) , y leo de la BD el iva (1,21€) y el precio sin iva (5.79€). Si hiciera otra vez el cálculo a la inversa, calcularía 5.79€*1.21 => 7.0059€, y ya estaríamos otra vez con el puñetero 7,01€.

- si quiero vender un artículo a 5.79€ más iva, calculo el iva con 5.79€*0.21 => 1.2159€, que redondeado son 1.22€ y lo sumo al precio para conseguir el precio final : 5.79+1.22 => 7.01€, pero guardo en la base de datos que el precio "bueno" es el precio sin iva.

En esta dirección se puede leer el boe con la información de cómo se puede hacer (es del 98, de cuando iba a llegar el euro):
http://www.boe.es/boe/dias/1998/12/18/pdfs/A42460-42471.pdf

Pero bueno, resumiendo, que para vender algo a 7€ de precio final, hay que hacer redondeos a 1 céntimo , al más cercano, permitiendo un descuadre de 1 céntimo, así que "legalmente" en una factura nos podremos encontrar con que:
BASE 5.78€ + 21% de IVA (1.2138€ redondeado a 1.21€) => TOTAL 6.99€
BASE 5.79€ + 21% de IVA (1.2159€ redondeado a 1.22€) => TOTAL 7.01€
(IMPOSIBLE VENDER ALGO A 7€ CON IVA)
y a la inversa se permite que:
TOTAL 7,00€ => BASE 5.78€+21% iva (1.21€)
TOTAL 7,00€ => BASE 5.79€+21% iva (1.22€)

En fin chicos , perdonad tanto follón, Gracias por la ayuda. Un saludo para todos.
Windows 10 + FWH 20.08 + BCC 7.4 + Harbour 3.2.0 + PSPad 5.0.3
User avatar
informaticaeloy
 
Posts: 118
Joined: Fri Dec 20, 2013 10:39 am
Location: Zaragoza, España

Re: Problema con redondeo

Postby D.Fernandez » Sat Jan 25, 2014 10:42 am

Eloy: La funcion que pongo funciona bien. Fíjate que hago 2 redondeos.

xRound( xRound())
el xRound() de adentro a 3 decimales y el de afuera a 2 decimales.
Primero a 3 decimales y luego a dos, me funciona bien aquí.

MsgInfo(xround( xROUND(7/1.21,3),2 ) )
MsgInfo(xRound( xROUND(7/1.21,3),2 ))
MsgInfo(xRound( xROUND(7/1.21,3),2 ) - 7 )

MsgInfo(xround( xROUND(8/1.21,3),2 ) )
MsgInfo(xRound( xROUND(8/1.21,3),2 ))
MsgInfo(xRound( xROUND(8/1.21,3),2 ) - 8

Saludos
Dario Fernandez
FWH 22.12, Harbour, MVS2022 Community, BCC, MySql & MariaDB, Dbf/Cdx VSCode.
Maldonado - Uruguay
D.Fernandez
 
Posts: 455
Joined: Wed Jul 31, 2013 1:14 pm
Location: Maldonado - Uruguay

Next

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 79 guests