PDA

Ver la Versión Completa : 1+1=3 ?


luisny
21-11-2003, 17:09:36
Hola a todos.

Me dirijo a ustedes porque me pasa lo siguiente en Delphi 7 Professional.


Mi problema es con la función format y para ilustrarlo tengo 2 ejemplos muy sencillos.


1º) ejecutar lo siguiente, donde Label1 es un simple TLabel


Label1.Caption:=format('%.2n',[1055.885]);

-Como resultado el valor obtenido es 1055,89 lo cual es del todo correcto.


2º) probar ahora con lo siguiente donde d es de tipo double.


d:=1055.885
Label1.Caption:=format('%.2n',[d]);


-El resultado obtenido es 1055,88 lo cual no es correcto.


Si lo prueban podrán comprobar esta circunstancia la cual me está generando bastantes problemas dentro de una aplicación que he desarrollado.

Personalmente interpreto que es un error que tiene el Delphi; pero me gustaría conocer otras opiniones.

Gracias.

roman
21-11-2003, 17:26:43
Ambos resulatdos son correctos: el 5 está a la mitad entre un número y otro de manera que la decisión de a cuál de ellos redondear es totalmente arbitraria. Lo que si es que en estos momentos desconozco el porqué en un caso se toma una decisión y en el otro otra. Posiblemente tiene que ver con la forma en que Delphi interpreta el parámetro cuando lo pasas directamente. Por ejemplo, si en lugar de usar un Double utilizas un Single verás que redondea hacia arriba.

Para solucionar esto usa la funcion SetRoundMode de la unidad math.pas:

SetRoundMode(rmUp);

// Saludos

jachguate
21-11-2003, 17:45:31
Seguramente el problema se da por la precision del Double. No tengo delphi a mano para comprobarlo, pero seguramente cuando pones el valor constante, el compilador no lo almacena en un double, sino en otro tipo de dato, que por alguna razón es mas preciso (al menos en este caso).

Si examinas el valor que queda almacenado en la variable d después de hacer la asignación, seguramente no será exactamente 1055.885, sino algo mas parecido a 1055.88499999999 de manera que el redondeo que aplica para la representación textual es correcto. Podes intentar utilizar otro tipo de dato, o bien sumarle un valor infimo que sea suficiente para aplicar un redondeo "correcto". Digamos 0.0001. Esto es una verdadera chapuza, pero realmente funciona.

Hasta luego.

;)

luisny
21-11-2003, 18:49:06
Gracias a todos por contestar tan rápido. En especial a Román; aunque no me convence mucho lo de que …el 5 está a la mitad entre un número…, he utilizado la función que sugerías SetRoundMode(rmUp) y perfecto.


Gracias de nuevo.

roman
21-11-2003, 19:07:04
luisny comentó:
aunque no me convence mucho lo de que …el 5 está a la mitad entre un número…,

Distancia entre 1055,885 y 1055,88 = 0,005
Distancia entre 1055,885 y 1055,89 = 0,005

// Saludos

luisny
21-11-2003, 20:31:05
CUIDADO con QuickReport y poner SetRoundMode(rmUp) .

Al generar unos informes se produce un error stack overflow.

Si quito SetRoundMode(rm) todo va perfecto.

Asi que estoy como al principio:(

roman
21-11-2003, 20:40:04
luisny comentó:
CUIDADO con QuickReport y poner SetRoundMode(rmUp) .

Al generar unos informes se produce un error stack overflow.


De ser así es un problema de QuickReport y habrá que reportarlo.

Algo que quizá funcione sea restaurar el modo de redondeo en cuanto termines:


var
RoundMode: TFPURoundingMode;

begin
RoundMode := GetRoundMode;
SetRoundMode(rmUp);
Label1.Caption:=format('%.2n',[d]);
SetRoundMode(RoundMode);
end;


// Saludos

erickpch
22-11-2003, 00:40:08
En parte de trucos del club hay una funcion que redondea correctamente al menos ami nunca me falla no recuerdo quien la puso peor la funcion es RoundD revisala ok...... asi te evitas los errores con Quick Report....

erickpch
22-11-2003, 00:54:50
Olvide desirte que la explicacion al "problema " de redondeo lo encuentras explicado en...

http://www.clubdelphi.com/vertruco.php?id=130

Ahora la funcion que te dije antes no la encuentro en el club, de repente la encontre en otro sitio web, de todas maneras mañana la copio y la pongo en el hilo...