Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-11-2008
agustibaldo agustibaldo is offline
Miembro
 
Registrado: nov 2006
Posts: 105
Poder: 18
agustibaldo Va por buen camino
Problema de Redondeo de Decimales con una Función

Estimados amigos de Club Delphi, en esta oportunidad les escribo porque tengo un problema bastante raro con una función que intenta obtener solo dos decimales de un valor.

Concretamente tengo lo siguiente:

Código:
function TFormPrincipal.TruncarDecimales (parametro: Double):Double;
begin
  Result := (Int(parametro * 100)) / 100;
end;
la cual llamo y grabo el resultado en una variable de la siguiente manera:

Código:
IMPORTE_TOTAL := TruncarDecimales(IMPORTE);
donde IMPORTE_TOTAL e IMPORTE son de tipo Doubles.

El problema se presenta cuando graba el resultado. Supongamos que, al momento de llamar a la función, IMPORTE = 190.950; cuando graba en IMPORTE_TOTAL el resultado es 190.94.-

Realmente no se que puede estar pasando. He probado declarar tanto la function como las variables como tipo Extended pero sigue persistiendo el problema.

Desde ya muchas gracias por su tiempo.
Saludos a todos.
Responder Con Cita
  #2  
Antiguo 07-11-2008
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 17
rgstuamigo Va por buen camino
Thumbs up

hola agustibaldo, yo lo veo raro lo que estas haciendo en tu funcion TruncateDecimales;sinceramente no hace nada esa funcion por que primero lo multiplicas * 100 y luego lo divides por el mismo 100 . no surte ningun efecto con lo que esta entrando, osea lo mismo que entra esta saliendo.......No se realmente lo que quieres hacer con esa funcion......
Saludos.........
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7

Última edición por rgstuamigo fecha: 07-11-2008 a las 21:31:05.
Responder Con Cita
  #3  
Antiguo 07-11-2008
Avatar de ContraVeneno
ContraVeneno ContraVeneno is offline
Miembro
 
Registrado: may 2005
Ubicación: Torreón, México
Posts: 4.738
Poder: 24
ContraVeneno Va por buen camino
Es broma ¿no?

multiplicas por 100 y luego divides por 100....
además, ¿que tiene de malo la función "int"?
¿para que crear otra?
__________________


Última edición por ContraVeneno fecha: 07-11-2008 a las 22:54:29.
Responder Con Cita
  #4  
Antiguo 07-11-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Que sí, que la función está bien.

multiplica por 100
coge la parte entera !!
divide entre 100

(la primera vez que ví la función, también me pasé por alto el "int" y los paréntesis )

El segundo paso se os coló , que precisamente es la que elimina los posibles decimales que tenga. Así solo se queda con 2 decimales.

Yo declaraba todas las variables como Currency y así evitaba esa función y el fallo inherente a los Floats/Extended que nunca guardarán el valor que representa, siempre guardará una aproximación.

Si usas Bases de datos, cambia el tipo también a Currency o NUMERIC(10,2) (en interbase y firebird con dialecto 3).

Si eso, pregunta .

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #5  
Antiguo 07-11-2008
Avatar de ContraVeneno
ContraVeneno ContraVeneno is offline
Miembro
 
Registrado: may 2005
Ubicación: Torreón, México
Posts: 4.738
Poder: 24
ContraVeneno Va por buen camino
cierto, cierto, mea culpa

En SQL Server, el tipo de dato para el campo es "money" o "decimal(10,2)"

¿"FormatFloat" hubiera servido?
__________________

Responder Con Cita
  #6  
Antiguo 08-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Hola, si usas Round

Código Delphi [-]
function TForm1.TruncarDecimales (parametro: Double): Double;
begin
  Result := (Round(parametro * 100)) / 100;
end;

solucionado
Responder Con Cita
  #7  
Antiguo 08-11-2008
Avatar de ContraVeneno
ContraVeneno ContraVeneno is offline
Miembro
 
Registrado: may 2005
Ubicación: Torreón, México
Posts: 4.738
Poder: 24
ContraVeneno Va por buen camino
¿ la función "RoundTo" serviría para eso?
__________________

Responder Con Cita
  #8  
Antiguo 08-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Si. En mi delphi no esta (v.5) pero si, parece que hace exactamente eso.
Responder Con Cita
  #9  
Antiguo 08-11-2008
Avatar de ContraVeneno
ContraVeneno ContraVeneno is offline
Miembro
 
Registrado: may 2005
Ubicación: Torreón, México
Posts: 4.738
Poder: 24
ContraVeneno Va por buen camino
supongo que "SimpleRoundTo" también serviría. Dependiendo del resultado final que se quiera.

Y no creo que sea dificil de implementar:
Código Delphi [-]
function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
var
  LFactor: Double;
begin
  LFactor := IntPower(10, ADigit);
  if AValue < 0 then
    Result := Trunc((AValue / LFactor) - 0.5) * LFactor
  else
    Result := Trunc((AValue / LFactor) + 0.5) * LFactor;
end;
__________________

Responder Con Cita
  #10  
Antiguo 10-11-2008
agustibaldo agustibaldo is offline
Miembro
 
Registrado: nov 2006
Posts: 105
Poder: 18
agustibaldo Va por buen camino
Ante todo, muchas gracias por sus respuestas.

Voy a probar usar la función Round para ver si ésta resuelve mi problema. En un primer momento no se me ocurrió porque, según tengo entendido, esta función redondea decimales, y lo que yo busco es mostrar solo 2 decimales, no redondear. De todas formas, intentaré esta forma para ver que resulta. Luego les comento.

Estoy trabajando con SQL Server 2005 y el tipo del campo IMPORTE es decimal(22,7)

Un abrazo a todos...
Responder Con Cita
  #11  
Antiguo 10-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Si, round redondea decimales, por eso mismo transforma 1.9465*100 = 194.65 en 195, mientras que int a secas tansolo te cogeria el valor entero (194). De todas maneras, la funcion RoundTo que te comenta contraveneno hace exactamente lo que querias implementar. saludos.
Responder Con Cita
  #12  
Antiguo 10-11-2008
agustibaldo agustibaldo is offline
Miembro
 
Registrado: nov 2006
Posts: 105
Poder: 18
agustibaldo Va por buen camino
Exacto, por eso me quedaba la duda. Al utilizar la función ROUND redondeo los decimales, y para el caso en que el valor sea pej. 190.857, el resultado de esta función será 190.86, lo cual no es lo que deseo.

Voy a probar usar ROUNDTO para ver que resulta. Tenes idea cual es la diferencia entre una y otra?

Muchas gracias por sus respuestas
Responder Con Cita
  #13  
Antiguo 10-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
si, pero si multiplicas por 100zzzZZZzzz lo que te puse funciona a la perfeccion. saludos.
Responder Con Cita
  #14  
Antiguo 10-11-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Pues ahora no me cuadran las cosas.

Tienes definido en la base de datos que almacene con una precisión de 7 decimales, lo cual me parece correctísimo para no perder decimales en operaciones de tanto por ciento, divisiones, etc y, ¿ahora no quieres redondear?, ¿quieres despreciar toda esa exactitud que te está dando los 7 decimales? no lo entiendo .

Yo lo que haría es especificar en delphi, (en los campos persistentes) la propiedad del TField Currency a true. Esto hace que se redondee a 2 decimales cuando se va a mostrar el dato, pero realmente guardará toda la precisión que quieres.

Por otra parte y al menos en españa, se permite legalmente redondear el monto total de una factura, pero no así las subpartes (iva, base imponible, etc). Tenlo en cuenta.

Otro detalle más (por si fueran pocos ) Mira con detenimiento las funciones RoundTo, simpleRoundTo, etc, ya que alguna de ellas depende de un parámetro de configuración del sistema, y determina si usará el tipo de redondeo (hacia el positivo más alto, hacia el positivo más bajo, etc).

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #15  
Antiguo 10-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Cita:
para el caso en que el valor sea pej. 190.857, el resultado de esta función será 190.86, lo cual no es lo que deseo.
no cuadra : antes buscabas que se redondeara ¿ahora ya no? de todas maneras, tanto la funcion escrita como el RoundTo o la implementacion de contraveneno te funcionaran. saludos.

Última edición por coso fecha: 10-11-2008 a las 13:00:48.
Responder Con Cita
  #16  
Antiguo 10-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
mmmm vale, ahora te entiendo. RoundTo. Aunque correctamente para cogerte 2 decimales te tendria que redondear el ultimo. saludos.

Última edición por coso fecha: 10-11-2008 a las 12:58:09.
Responder Con Cita
  #17  
Antiguo 10-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
... o bien esto

Código Delphi [-]
function TForm1.TruncarDecimales (parametro: Double): Double;
begin
  Result := Floor(parametro * 100)/100;
end;

esto si que creo que es lo que querias. saludos.
Responder Con Cita
  #18  
Antiguo 10-11-2008
agustibaldo agustibaldo is offline
Miembro
 
Registrado: nov 2006
Posts: 105
Poder: 18
agustibaldo Va por buen camino
Estimados amigos, es probable que no me haya explicado bien. Por eso trataré de ser lo más claro posible.

Con respecto al cuestionamiento de [lepe] te comento que estoy trabajando con la BD de un ERP Nacional (de Argentina) que no construimos nosotros. Solo hacemos aplicaciones que manipulan datos del antes mencionado. Si bien este campo que necesito grabar tiene una precisión de 7 decimales, a los fines prácticos de la aplicación que estamos desarrollando solo se necesitan 2 decimales. Por esta razón, es que necesito obtener solo dos decimales.

Y en cuanto al planteo que me hace [coso], es probable que la palabra "redondear" no sea la mas adecuada para este caso y se pueda prestar a confusiones. Concretamente necesito "truncar" la cantidad de decimales que tiene un valor a 2. Algunos ejemplos:

Si tengo 190.253, necesito que el resultado sea 190.25
Si tengo 190.250, necesito que el resultado sea 190.25
Si tengo 190.258, necesito que el resultado sea 190.25

Es decir, necesito truncar la cantidad de decimales que muestra. Y grabar este resultado.

Lamento que haya surgido esta confusión y espero, esta vez, haber sido claro. Si no entienden algo por favor escriban y lo vuelvo a explicar.

Desde ya, muchísimas gracias por su tiempo.
Un abrazo.
Responder Con Cita
  #19  
Antiguo 10-11-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
No no tranquilo el ultimo codigo, con floor (unit math), trunca. Tambien existe la funcion trunc, pero no se porque obtenia el mismo resultado que con int. Debe ser por la imprecisión de los doubles. saludos.
Responder Con Cita
  #20  
Antiguo 10-11-2008
agustibaldo agustibaldo is offline
Miembro
 
Registrado: nov 2006
Posts: 105
Poder: 18
agustibaldo Va por buen camino
la verdad, [coso], no se como agradecerte. Genio total!!!
Probé FLOOR y funciona perfectamente.

Muchas gracias a todos los que me dieron una mano con esto.
Un abrazo.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
problemas con redondeo (decimales) Milperrimo Varios 4 26-01-2008 05:33:03
Redondeo de decimales Cheswar Varios 3 07-10-2007 21:31:10
redondeo a 2 decimales torito Varios 4 22-12-2004 18:36:34
funcion de redondeo de decimales Rabata Varios 2 29-09-2003 02:41:39
Problema de redondeo cmgenny Varios 3 08-08-2003 20:16:38


La franja horaria es GMT +2. Ahora son las 17:15:37.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi