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 14-09-2010
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Recién leo el hilo nuevamente...

Y coincido cien por ciento con Delphius.
Un error que por defecto o exceso ajustemos en diezmilésimas, podrían convertirse en centesimas, por ejemplo.

Saludos.

Última edición por ecfisa fecha: 14-09-2010 a las 18:37:09.
Responder Con Cita
  #2  
Antiguo 14-09-2010
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
Cita:
Empezado por Casimiro Notevi Ver Mensaje
Estoy con Delphius, el modo propuesto por el amigo rrf está bien como ejercicio, pero no es práctico ni vale para el "mundo real", ya me imagino las caras de los clientes protestando por esos "redondeos" tan "cuadrados"

Creo que la función que he propuesto sí es válida para "la vida real":

function Redondeo (valor: Double; decimales: integer = 0): Double;

Indicas el valor a "redondear" y el número de decimales al que quieres el redondeo.
Exacto. No es como naturalmente medimos y trabajamos. Y además, es inútil intentar medir más allá de la escala que nos brinda las herramientas y a la que estamos interesados de aceptar como precisión. Esto se dice muy a menudo en las clases de cálculo.

Si uno acepta que sus mediciones serán precisas a 4 decimales, por dar un número, entonces sus mediciones no podrán ser mucho más precisas más allá de 5 decimales. Ergo... no tiene sentido continuar buscando más precisión. Por ejemplo:

Estoy midiendo la altura de un andamio con un metro convencional (al centímetro)... y justo la marca está entre los 3,20 y 3,21. No tiene sentido práctico que pretenda medir hasta las milésimas si la cinta métrica no tiene esa unidad de medida. ¿Que valor tomo? ¿3,20 o 3,21? Según esta regla, ... no tengo otra elección... o asumo 3,20 ó 3,21. No puedo asegurar si es 3,205 o 3,209, 3,201... o cualquier otro número que esté en el rango [3,20; 3,21]

Es por ello que una vez finalizada la medición, se adopta un criterio de redondeo.
Y Por más preciso que sean los cálculos el valor exacto podría (y estará) en un margen de +- 0,5 ulp.
Hagamos de cuenta que me consigo un metro con escala al milímetro... llego a que mide 3,203. El valor más preciso y exacto estará en el rango [3,2025; 3,2035].

Cita:
Empezado por ecfisa Ver Mensaje
Hola.

Recién leo el hilo nuevamente...

Y coincido cien por ciento con Delphius.
Un error que por defecto o exceso ajustemos en diezmilésimas, podrían convertirse en centesimas, por ejemplo.

Saludos.
Exacto. Y como dije, ir redondeando desde más decimales a menos es una técnica que irá acumulando el error.

Creo que mis explicaciones se ilustrará mejor con una regla:

Código:
+|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||+
|         |         |         |    *    |         |         |
0                   1                   2                   3
+-----------------------------------------------------------+
El * indica el número más exacto que podemos medir a esa escala. Subamos (o mejor dicho, bajemos) de decimales... Ahora en esta nueva escala tenemos dos opciones de redondeo:

Código:
+-|-|-|-|-+-|-|-|-|-+-|-|-|-|-+-|-|-|-|-+-|-|-|-|-+-|-|-|-|-+
|         |         |         |   * *   |         |         |
0                   1                   2                   3
+-----------------------------------------------------------+
Sigamos... veamos como ahora el efecto de redondeo nos va alejando:

Código:
+---------+---------+---------+---------+---------+---------+
|         |         |         |         |         |         |
0                   1         *         *                   3
+-----------------------------------------------------------+
Y por último:

Código:
+-------------------+-------------------+-------------------+
|                   |                   |                   |
0                   *                   *                   3
+-----------------------------------------------------------+
Como se aprecia, cada vez el rango del error absoluto se ve incrementado debido a los redondeos por exceso y por defecto.

Quizá para ciertos números el algoritmo que implementado rrf no provoque demasiada perturbaciones, pero en lo general no es óptimo. Pruébese con decimales como: ,1919191919... o ,91919191... o incluso com estos: ,454545... y ,54545454...

Creo que con ello queda más que evidente el porqué es inútil asumir decimales y redondeos más allá de lo que estamos dispuestos a tolerar.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #3  
Antiguo 14-09-2010
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
Ha... por cierto, recomiendo que se de una revisión a la unidad Math... Hay una buena cantidad de funciones, para lo que se ha estado debatiendo y viene al caso están las funciones: Round, RoundTo, SimpleRoundTo, además de Ceil y Floor y la posibilidad de indicar el modo de redondeo.

Amigo Casi, tu función me recuerda mucho a SimpleRoundTo.

Código Delphi [-]
function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
var
  LFactor: Double;
begin
  LFactor := IntPower(10, ADigit);
  Result := Trunc((AValue / LFactor) + 0.5) * LFactor;
end;

Por último, no olvidarse que en el mundo de la aritmética flotante no existe exactitud absoluta . Por más exactamente redondeadas que sean las implementaciones de las operaciones soportadas por el estándar IEEE 754 estamos sujetos a ciertas imprecisiones y limitaciones.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #4  
Antiguo 14-09-2010
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.052
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por Delphius
[..]Amigo Casi, tu función me recuerda mucho a SimpleRoundTo.

Código:
function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
var   LFactor: Double;
begin
   LFactor := IntPower(10, ADigit);
   Result := Trunc((AValue / LFactor) + 0.5) * LFactor;
end;

hasta el nombre de las variables se parecen, esa función la hicimos entre mi compañero y yo, un día en la que estábamos desesperados con los redondeos y dijimos "de hoy no pasa, hacemos una función que redondee de verdad". Y nos salió esa que he puesto.
Seguramente los de delphi se copiaron de nosotros
Responder Con Cita
  #5  
Antiguo 14-09-2010
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
Cita:
Empezado por Casimiro Notevi Ver Mensaje
hasta el nombre de las variables se parecen, esa función la hicimos entre mi compañero y yo, un día en la que estábamos desesperados con los redondeos y dijimos "de hoy no pasa, hacemos una función que redondee de verdad". Y nos salió esa que he puesto.
Seguramente los de delphi se copiaron de nosotros
Pues ya ves, como son las cosas... ¡Que te paguen los derechos de autor!

Choca los 5 amigo, yo empecé a meterme más en esto de los números, el redondeo, cálculo y demás hace unos meses tras recibir unos Horrores de números

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #6  
Antiguo 06-08-2012
Avatar de TheJHorse
TheJHorse TheJHorse is offline
Miembro
 
Registrado: dic 2005
Posts: 13
Poder: 0
TheJHorse Va por buen camino
Se que el tema esta ya tocado, pero quisiera reincidir en el ejemplo del amigo rrf, pero a solo 2 digitos, aca todos empiezan a nombrar y decir que no se aplica a la realidad, pero quisiera poner el siguiente ejemplo:

Un supermercado que gira facturas al dia en un promedio de 15000 facturas tan solo en uno de sus locales, donde calculos de total: 1.33333333 segun ustedes deberia ser redondeado a 1.33 donde claramente hay una perdida de 0.00333333 centavos para la empresa diario de 50 centavos, 1500 mensual, 18000 anual, tan solo de una sede; lleven el caso para un banco donde las transacciones son aun mayores.

No creo que se deba decir tan alegremente y confiadamente que algo no se aplica a la realidad, por que la realidad mis queridos amigos es absurdamente coherente.
__________________
PhC Rulez
Responder Con Cita
  #7  
Antiguo 06-08-2012
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.052
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Hola, no es así, además de que ninguna empresa, y la de tu ejemplo menos, no pierden dinero, al contrario, ganarán más

Primero, todo depende de la necesidad, una empresa puede querer/necesitar redondear a 2 decimales y tiene que hacerlo de esa forma. Entonces no queda más remedio que redondear.
Segundo, no puedes pedirle a un cliente, en tu caso de ejemplo, que pague 0,00333333 porque no se puede, prueba a pagar tú mismo esa cantidad, lo mínimo que puedes pagar en cualquier sitio, negocio, tienda, banco, etc. es un céntimo: 0,01
Tercero, entonces en tu caso, ¿cuánto le cobras al cliente?, pues eso, 1 céntimo, y ¿qué ocurre?, pues ahora resulta que la empresa no ha perdido 0.00333333 sino que ha ganado: 0,00666666 que multiplicado por tus 15000 facturas, son 99,9999 que al año sería 1199,9988 (1200 céntimos), o sea, en 180000 facturas (15000x12) habrá ganado 12 euros/dólares/loquesea al año.
Y cuarto, como dije al principio, todo depende de las necesidades que se tengan, no es lo mismo el redondeo de una factura (que va a 2 decimales), que los cálculos científicos de algún proyecto ultra preciso que se mide en micrómetros, por decir algo.
Y en este caso, el usuario necesitaba redondear a 2 decimales.
Aunque con la función que hemos presentado se puede redondear a los decimales que se necesite, que es de lo que se trata.




Cita:
Empezado por TheJHorse Ver Mensaje
Se que el tema esta ya tocado, pero quisiera reincidir en el ejemplo del amigo rrf, pero a solo 2 digitos, aca todos empiezan a nombrar y decir que no se aplica a la realidad, pero quisiera poner el siguiente ejemplo:

Un supermercado que gira facturas al dia en un promedio de 15000 facturas tan solo en uno de sus locales, donde calculos de total: 1.33333333 segun ustedes deberia ser redondeado a 1.33 donde claramente hay una perdida de 0.00333333 centavos para la empresa diario de 50 centavos, 1500 mensual, 18000 anual, tan solo de una sede; lleven el caso para un banco donde las transacciones son aun mayores.

No creo que se deba decir tan alegremente y confiadamente que algo no se aplica a la realidad, por que la realidad mis queridos amigos es absurdamente coherente.
Responder Con Cita
  #8  
Antiguo 30-05-2015
Chaja Chaja is offline
No confirmado
 
Registrado: ago 2004
Ubicación: Mar del Plata
Posts: 238
Poder: 0
Chaja Va por buen camino
Hola...

Tratando desde hace tiempo encontrar solucion para este problema, veo que no fue solo a mi que se rompio la cebeza de como solucionarlo. Yo uso RoundTo(), pero a veces me falla. En definitiva cual es la rutina mas acertada para usar, despues de tantas explicaciones de Delphius, que quisiera que fuese mi socio por lo que sabe, y por que esta mas cerca de donde vivo, sin desmerecer a los demas. ejemplo tengo una cifra que es 45,555 y si la redondo a dos me queda 45,55.
Gracias a todos por existir....

Luis Roldan
Mar del Plata
Argentina
Responder Con Cita
  #9  
Antiguo 30-05-2015
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
Chaja,

Cita:
Empezado por Chaja
...uso RoundTo...pero a veces me falla...cual es la rutina mas acertada para usar...ejemplo tengo una cifra que es 45,555 y si la redondo a dos me queda 45,55...


Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Math;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function RoundTo(F: single; D: integer): double;
var
   P : double;
begin
   P := Power(10, D);
   Result := Trunc(F * P + 0.5) / P;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   N1, N2 : Double;
   MsgUsr : String;

begin

   N1 := 45.555;
   N2 := RoundTo(N1,2);

   MsgUsr := 'N1 (Valor Original) = %g ' + #13#10 + #13#10 + 'N2 (Valor redondeado a 2 decimales) = %g';

   MessageDlg(Format(MsgUsr,[N1,N2]),mtInformation,[mbOK],0);

   N1 := 3.1415927;
   N2 := RoundTo(N1,3);

   MsgUsr := 'N1 (Valor Original) = %g ' + #13#10 + #13#10 + 'N2 (Valor redondeado a 3 decimales) = %g';

   MessageDlg(Format(MsgUsr,[N1,N2]),mtInformation,[mbOK],0);


end;

end.
El código anterior en Delphi 7 sobre Windows 7 Professional x32, Permite realizar redondeos por exceso, como se muestra en la siguiente imagen:



Nota : La función de redondeo del ejemplo fue tomada de : Como redondear a partir del numero 5 .

Espero sea útil

Nelson.
Responder Con Cita
  #10  
Antiguo 14-09-2010
rrf rrf is offline
Miembro
 
Registrado: ago 2003
Ubicación: S/C Tenerife, España
Posts: 454
Poder: 21
rrf Va por buen camino
Red face

Hola de nuevo.

Oye Delphius, gracias por tu explicación. No he hecho pruebas, pero parece que tienes razón y además, las demás opiniones te apoyan.

Cambiando de tema, creo que tienes habilidades para dedicarte a la docencia (y va en serio).

Ahora sí, amplío la información sobre esa función. He trabajado con el cálculo de % de una serie de valores. Redondeo a 2 decimales, pero es frecuente que la suma de los resultados finales sea un 100,01%, 100,02%, 99,99% ó 99,98%.

Lo que me parece un error "demasiado grande". Pero, por más que hice pruebas, no logré mejorar mucho los resultados.

Finalmente me quedó la idea de que posiblemente si hacía un redondeo como el que propuse en mi comentario anterior, la situación mejoraría.

No llegué a hacer la función hasta que leí este hilo en el foro. "Sobre la marcha", hice las pruebas y añadí el comentario. En la práctica, no lo probé mas que con un par de ejemplos.

Sin embargo, después de leer tu comentario Delphius y el de Casimiro y Ecfisa, creo ver que seguramente es un planteamiento equivocado.

Gracias por las aclaraciones y salu2.
Responder Con Cita
  #11  
Antiguo 14-09-2010
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
Cita:
Empezado por rrf Ver Mensaje
Hola de nuevo.

Oye Delphius, gracias por tu explicación. No he hecho pruebas, pero parece que tienes razón y además, las demás opiniones te apoyan.
De nada. Pues yo si probé la función que pusiste. Al principio sospeché que era yo el que estaba equivocado y que al final podría resultar pero cuando empecé a mirar más adentro, y probar con los números extremos noté como se hacía pedazos el algoritmo.
Si aplica un redondeo razonable para ciertos números es una casualidad, pero en lo general... lo siento pero no eso no vale.

Si me apoyan es que les he dado una coima jajaja. No es que me apoyen ciegamente, ellos seguramente saben mucho más de lo que puedo saber yo... además ellos ya venían probando y proponiendo.
Nomás es que yo me animé a darle un pequeño giro al asunto.

Cita:
Empezado por rrf Ver Mensaje
Cambiando de tema, creo que tienes habilidades para dedicarte a la docencia (y va en serio).
No eres el primero en decírmelo... ¡hasta el sodero opina que debería ser docente/profesor!
Hechando a perder dicen que se aprende... el asunto es que si enseño estaré hechando a perder a algunos jóvenes y futuros profesionales.

Debo reconocer que todavía me lo pregunto si vale la pena y me encantaría... el asunto es si los aguanto (y ellos a mí, que es lo principal).

Cita:
Empezado por rrf Ver Mensaje
Ahora sí, amplío la información sobre esa función. He trabajado con el cálculo de % de una serie de valores. Redondeo a 2 decimales, pero es frecuente que la suma de los resultados finales sea un 100,01%, 100,02%, 99,99% ó 99,98%.

Lo que me parece un error "demasiado grande". Pero, por más que hice pruebas, no logré mejorar mucho los resultados.
Como dije en mi último post: la aritmética de punto flotante no es 100% exacta, más bien es aproximada. Tiene que ver no sólo el tipo de datos (y su precisión), sino también el modo de redondedo, los algoritmos, y en el modo de trabajar internamente.

El formato IEEE 754 impone cierto formato y los números deben adaptarse a éste. Por empezar hay un límite de dígitos significativos a almacenar en los tipo Simple, Double y Extended. Esto hace que los números no pueden ser más precisos de esa cantidad de dígitos. En segundo lugar no todos los números son exactamente representables en el formato por lo que la máquina en realidad almacena un número aproximado (como por ejemplo, 0.1). Y peor aún en los números irracionales... como Pi, la constante de euler... donde los efectos son más notables: no sólo se ven limitados por la precisión sino que no son representables. Otros números que tienen problemas son los números periódicos... 1/3 es 0,333333....

Y por último, el estándar IEEE 754 establece que las operaciones sean redondeadas. En síntesis, son muchas cosas que afectan y por ello nunca se conseguirá una total exactitud. Es por ello que cuando se trata de operaciones con números flotantes se estila trabajar con márgenes de error.

No quisiera extenderme demasiado, busca entre los foros "Lo que todo informático debe saber sobre aritmética flotante". He hablado antes al respecto. O mejor aún te hago llegar el enlace a material de consulta.

Creo que con ello tienes para darte una mejor idea del tema.

Cita:
Empezado por rrf Ver Mensaje
Finalmente me quedó la idea de que posiblemente si hacía un redondeo como el que propuse en mi comentario anterior, la situación mejoraría.
Pues, ya vez que no

Cita:
Empezado por rrf Ver Mensaje
No llegué a hacer la función hasta que leí este hilo en el foro. "Sobre la marcha", hice las pruebas y añadí el comentario. En la práctica, no lo probé mas que con un par de ejemplos.

Sin embargo, después de leer tu comentario Delphius y el de Casimiro y Ecfisa, creo ver que seguramente es un planteamiento equivocado.

Gracias por las aclaraciones y salu2.
Gracias nuevamente.
No tienes que agradecerme. Aquí se aprende todos los días, y te lo digo yo que me falta mucho por aprender . No te creas que se mucho de mucho, nomás es que hago un esfuerzo para aparentar que se mucho

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
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
Como redondear un numero en un procedimiento en Firebird Gaby123 SQL 0 26-02-2007 18:25:26
Cómo Redondear a 4 decimales un campo de tipo Numérico vick Conexión con bases de datos 1 11-10-2005 01:04:23
Funcio para obtener las decimas de segundo enzo Varios 2 13-05-2005 01:06:11
Mostrar un Float como un hh:mm:ss rjsitruiz Impresión 2 04-07-2004 14:25:29


La franja horaria es GMT +2. Ahora son las 05:13:25.


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