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 18-04-2011
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Unhappy No entiendo el uso de decimales

Hola amigos.

He tenido un problema (no se si ocurrira solo con D7 que es con el que trabajo) ya que cuando trabajo con numeros flotantes tiende a agregarme decimales. No le habia dado importancia hasta q mi cliente protestó porque cuando el hace una factura, la guarda y la recupera las cantidades no coinciden entre la factura que ha impreso y la que esta guardada.

Ejemplifico:

Ahorita estoy debuggeando un programa en el cual yo escribo por ejemplo 8.52 en un DecimalSpin. Al acceder a su propiedad "value" para obtener el numero me agrega digitos

Código Delphi [-]
cantidad := spin_cant.value; {Escribi 3, obtengo 3}
precio := spin_precio.value;  {Escribi 8.52, obtengo 8.5217390006}
total := cantidad * precio; 
{De esta manera me regresa 25.5652170018
al momento de ponerlo en la factura utilizando un FormatFloat obtengo 25.57
pero si hacemos la multiplicacion original obtenemos 25.56 que es lo correcto}

Como pueden notar el error es de solo 0.01 pero en una factura con 10 o 20 productos hacen variaciones de 10 a 20 centavos.

Pensé que el problema podría ser el Control, sin embargo me repite el mismo problema con cualquier otro control para decimales.
De hecho hice otro experimento

Código Delphi [-]
var
 s1,s2 : string;
 tmp : single;
begin
 precio := spin_precio.value;  
 s1 := FormatFloat('###########0.00;-###########0.00;0',  precio);
 s2 := FormatFloat('###########0.00;-###########0.00;0',  cantidad);
 //Ahora si, en s2 tengo 8.52
 tmp := StrToFloat(s1) * StrToFloat(s2);
 //Otra vez, en lugar de obtener 25.56 obtengo 25.559999416
end;

No entiendo el motivo de este comportamiento con los decimales. Asi que les pido tengan la gentileza de darme un poco de ayuda para corregir este problema.

Muchas gracias de antemano.
Responder Con Cita
  #2  
Antiguo 18-04-2011
mcs mcs is offline
Miembro
 
Registrado: may 2007
Ubicación: Girona
Posts: 229
Poder: 18
mcs Va por buen camino
Es porqué trabajas con variables de coma flotante (float o reals). Para evitar estos problemas de redondeo, se debe usar siempre variables de tipo Currency (que es coma fija).
Responder Con Cita
  #3  
Antiguo 18-04-2011
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.043
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por mcs Ver Mensaje
Es porqué trabajas con variables de coma flotante (float o reals). Para evitar estos problemas de redondeo, se debe usar siempre variables de tipo Currency (que es coma fija).
No solamente variables, obviamente, los campos de la base de datos también.
Responder Con Cita
  #4  
Antiguo 19-04-2011
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Thumbs up woW

A eso iba exactamente mi siguiente duda, ya que en MySQL me ocurria lo mismo. Ya estuve leyendo un poco y veo que para MySQL se debe especificar la columna como DECIMAL(M,D) pero me confunde un poco los parametros.

Para moneda cual seria la precision recomendada??
Por ahora estoy utilizando DECIMAL(4,2)

Gracias nuevamente, aprecio mucho su ayuda
Responder Con Cita
  #5  
Antiguo 27-04-2011
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Un poco de off-topic y de SPAM: Hace un tiempo escribí un artículo titulado El Valor de un Céntimo, que está relacionado con el tema del manejo de valores fraccionarios en computadoras digitales. Seguro que te clarifica las cosas.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #6  
Antiguo 27-04-2011
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola,

Lecturas obligadas:
1. What Every Computer Scientist Should Know About Floating-Point Arithmetic
2. Comparing floating point numbers
3. Floating point numbers

Creo que con ello uno ya se hace la idea.

Saludos,
PD: A quien no le guste el inglés como a mi, ármese de valor.
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #7  
Antiguo 27-04-2011
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.043
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por Ñuño Martínez Ver Mensaje
Un poco de off-topic y de SPAM: Hace un tiempo escribí un artículo titulado El Valor de un Céntimo, que está relacionado con el tema del manejo de valores fraccionarios en computadoras digitales. Seguro que te clarifica las cosas.
En la última gestión que tuve la suerte de decidir en todos los aspectos, también use algo similar, todos los importes se guardaban en un formato y se presentaban al usuario según la divisa que estuviese usando.
Responder Con Cita
  #8  
Antiguo 16-05-2011
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Unhappy Es mas de lo que pensé

Ok, Ahora tengo mucha tarea :S

Gracias por los valiosos consejos. Y le entraré con valor al inglés aunque no me gusta.
Responder Con Cita
  #9  
Antiguo 16-05-2011
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Thumbs up Inteligente truco

Cita:
Empezado por Ñuño Martínez Ver Mensaje
Un poco de off-topic y de SPAM: Hace un tiempo escribí un artículo titulado El Valor de un Céntimo, que está relacionado con el tema del manejo de valores fraccionarios en computadoras digitales. Seguro que te clarifica las cosas.
Ya lei el artículo, me pareció muy interesante la manera que propusiste sobre manejar los precios en formato de enteros

Cita:
En aquel programa, en lugar de almacenar el valor real de los productos guardábamos un valor ficticio y lo guardábamos como un número entero. Para obtener el valor real se dividía este número ficticio por un factor que dependía de la divisa; así para los euros dividíamos por 100.000, mientras que para obtenerlo en pesetas dividíamos por 601. Con este método nos quitamos dos problemas: la conversión entre divisas (importante, porque se hizo para un hotel, y además coincidió con el paso de la peseta al euro) y teníamos una precisión de hasta la milésima de céntimo de euro, más de lo necesario
Me podrías explicar un poco mas sobre este método que inventaste. ¿Cómo determinas el valor ficticio? ¿Podrias mostrarnos como lo usabas, por ejemplo para obtener dólares y euros?

Muchas gracias, excelente aporte
Responder Con Cita
  #10  
Antiguo 16-05-2011
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Cita:
Empezado por darkerbyte Ver Mensaje
Me podrías explicar un poco mas sobre este método que inventaste. ¿Cómo determinas el valor ficticio? ¿Podrias mostrarnos como lo usabas, por ejemplo para obtener dólares y euros?
Por supuesto que puedo explicarlo mejor. Eso sí, no lo inventé yo ya que no es sino un cambio de unidad, algo parecido a (por ejemplo) pasar de kilómetros a millas.

Verás, primero tenemos una tabla denominada divisa, más o menos así:
Código SQL [-]
CREATE TABLE divisas
  nombre VARCHAR (32),
  simbolo VARCHAR (4),
  valor INTEGER,
  num_decimales INTEGER
Ahora imaginemos que nuestra moneda principal serán los euros. En principio podríamos ponerle el valor "1", pero tiene céntimos así que sería más lógico que fuera "100". Sin embargo hay divisas cuyo valor es inferior al céntimo de euro (como la antigua peseta, por ejemplo) así que le damos el valor "10.000". Pues damos de alta a la divisa:
Código SQL [-]
INSERT INTO divisa (nombre, simbolo, valor, num_decimales)
VALUES ('euro', '€', 10000, 2);
Ahora metemos dólares. Primero, tenemos que saber cuántos euros es un dólar, que según Google, cuando escribo esto es 1U$ = 0'707063565€. Multiplicamos por el valor del euro, esto es, por 10.000, y nos sale 7.071:
Código SQL [-]
INSERT INTO divisa (nombre, simbolo, valor, num_decimales)
VALUES ('dólar estadounidense', 'U$', 7071, 2);
Ahora vamos a por los productos:
Código SQL [-]
CREATE TABLE productos
  nombre VARCHAR (256)
  precio INTEGER;
Como ves, el precio es un entero. Para introducir el precio, pues sólo tenemos que multiplicarlo por el valor de la divisa en la que hayamos introducido el precio:
Código SQL [-]
%VALOR_DIVISA% = SELECT valor FROM divisas WHERE nombre=%DIVISA_SELECCIONADA%;
INSERT INTO productos (nombre, precio)
VALUES ('chocolatina', (1.20 * %VALOR_DIVISA%));
Y ya está. Ahora todos los cálculos los hacemos con enteros, pero cuando mostremos el precio tenemos que dividir por el valor de la divisa y nos dará el precio.

Por ejemplo, nuestra chocolatina:
Código:
En euros:
  12.000 / 10.000 = 1'20€
En dólares:
  12.000 / 7.071 = 1'68U$
Que conste que esto no soluciona completamente el tema del redondeo. Es más, según Google la chocolatina cuesta 1'70U$: dos centavos más.

Espero que haya quedado más claro.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine

Última edición por Ñuño Martínez fecha: 17-05-2011 a las 10:12:08.
Responder Con Cita
  #11  
Antiguo 17-05-2011
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Thumbs up Podria marcar una tendencia

Hola de nuevo Ñuño.

Gracias por tomarte el tiempo y la molestia para esta excelente explicación. Ahora estoy evaluando de que manera puedo implementarlo al proyecto, aunque ahora es un poco complicado ya que habria que cambiar la estructura de la BD. Pero creo que el cambio bien valdría la pena.

Espero que pronto algunos mas de nuestros expertos comenten y enriquescan tu aporte, yo creo que incluso podría incluirse a la sección de Trucos.
Responder Con Cita
  #12  
Antiguo 17-05-2011
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola,
Lo que comenta Ñuño es más o menos similar a lo que comenté en una ocasión en un hilo en DA. La idea es que todo se opere a nivel de enteros y sólo a efectos de presentación se da su equivalente en formato real, con decimales.

Recomendaría la lectura de todo el hilo, ofrece un interesante planteo de lo que es el mundillo de los números flotantes.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #13  
Antiguo 17-05-2011
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.043
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Estas cosas son las que se aprenden con la experiencia, después de haber sufrido algún problema con clientes que no le cuadran las cuentas y tienes que volverte loco buscando una buena solución .
Responder Con Cita
  #14  
Antiguo 18-05-2011
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Cita:
Empezado por Delphius Ver Mensaje
Hola,
Lo que comenta Ñuño es más o menos similar a lo que comenté en una ocasión en un hilo en DA. La idea es que todo se opere a nivel de enteros y sólo a efectos de presentación se da su equivalente en formato real, con decimales.

Recomendaría la lectura de todo el hilo, ofrece un interesante planteo de lo que es el mundillo de los números flotantes.

Saludos,
Pues sí, muy interesante el hilo y las explicaciones.

Por cierto, que algunas bases de datos (como dBase) y lenguajes de programación (como COBOL) no usan punto flotante, sino algún tipo punto fijo (sea este en base decimal o binaria, o codificándolo diréctamente a ASCII), lo cual es más o menos lo que hemos explicado aquí y en el hilo que has enlazado. Incluso algunos microporcesadores, como el mítico Z-80, permitían operar directamente con BCD u otras notaciones de punto fijo. Creo que PowerPC permite usar tanto punto flotante como el fijo.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine

Última edición por Ñuño Martínez fecha: 18-05-2011 a las 10:59:41.
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
ayuda con mi tarea no entiendo!! chairez0490 Varios 3 16-12-2009 04:20:58
Cable de red que no lo entiendo Petolansa Redes 2 21-04-2009 14:55:33
no entiendo Intraweb davidvamo Internet 15 24-04-2008 05:34:16
No lo entiendo ramonibk MS SQL Server 11 20-05-2004 20:23:20
No entiendo rastafarey Firebird e Interbase 1 03-12-2003 17:14:30


La franja horaria es GMT +2. Ahora son las 04:07:08.


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