PDA

Ver la Versión Completa : operaciones con números float.


fjardelphi
28-04-2005, 09:46:23
Hola.
¿Hay alguna forma de fijar en las operaciones con números float que sólo se utilicen dos decimales sin utilizar funciones de redondeo? Necesito operar con euros donde sólo se visualicen dos números decimales. Con más detalle el problema es el siguiente:

Tengo una serie de lineas de detalle donde el importe es un campo calculado:
bi:= RoundTo(DetCANTIDAD.Value*DetPVP.Value, -2)
dt:= RoundTo(DetDESCUENTO.Value / 100 ) * Basimponible,-2);
DetccImporte.Value := bi - dt;

El total lo muestro utilizando un campo Agregado cuya expresión es:
SUM(Cantidad*pvp-((descuento/100)*Cantidad*PVP))

Problema: La suma no es exacta por los decimales y el redondeo.
¿Cómo solucionais los totales de un conjunto de lineas de detalle?

Saludos y gracias.

marcoszorrilla
28-04-2005, 14:22:32
Para eso yo me hice una función:

function RoundEuros(Const X: Double): Double;
var
r:Int64; //resto
X2:Int64; //número
x1:double; //resultado
begin
x2:=trunc((abs(x)*1000)+0.5); //Tomo los 3 primeros decimales.

r:=(x2 mod 10);//Compruebo si el 3 decimal es >=5
x2:=trunc(x2/10);//desprecio el tercer decimal

if r >= 5 then //Si el 3 decimal era >= 5 sumo 1 al número
x2:=x2+1;

x1:=x2/100; //Construyo el número con los 2 decimales

if x < 0 then
result:=0 - x1
else
result:=x1;

end;


Un Saludo.

Elfoscuro
28-04-2005, 15:54:37
Yo lo que haría sería sumar todos los totales de línea. El problema es que no es lo mismo (10+16%) + (10+16%) que (20+16%). Se va en algunos casos de 0,1 centimos de euro, y con el redondeo a veces se ve. De todas formas, si usas tres decimales para los precios y subtotales, falla bastante.

Resumiendo, no cojas el total sin Iva y sin descuento y le apliques los porcentajes. Suma los totales parciales por linea.

Saludos del elfo

jachguate
28-04-2005, 17:22:22
Para eso yo me hice una función:

No seria mas simple y con el mismo resultado:


uses Math;
.
.
.
function RoundEuros(Const X: Double): Double;
begin
Result := roundTo(x, -2);
end;


Hasta luego.

;)

fjardelphi
28-04-2005, 19:03:59
Así es como lo hago: roundto(valor, -2). Pero como trabajo con el campo agregado. Si los sumo yo no tengo problema, el problema es que en la expresión del campo agregado no es posible utilizar la función roundto.

JOSEPE
28-04-2005, 19:28:06
Bueno si utilizas bases de datos (que asi parece) IB o FB puedes utilizar alguna libreria UDF que hay varias y free, o puedes usar variables Numeric o Decimal.
Estoy de acuerdo con ELfoscuro cuando sugiere en primero calcular los parciales para luego sumar el total a partir de estos.

Saludos,
JOSEPE
Lima-Peru

jachguate
28-04-2005, 19:51:59
Podrias tener un campo calculado que ya haga el redondeo, y luego el agregado hacerlo sobre el campo calculado.

Hasta luego.

;)

marcoszorrilla
28-04-2005, 22:04:10
uses Math;
.
.
.
function RoundEuros(Const X: Double): Double;
begin
Result := roundTo(x, -2);
end;


El problema es que esta función no está dispnible en Delphi 5 y versiones inferiores.

Si existe en D7 y no sé en D6, yo debo reconocer que la cree para una versión de Access en que se les olvidó poner la opción redondeo y luego la adapté a Delphi 3 y hasta D5 la he venido utilizando sin ningún problema.

Un Saludo.

jachguate
28-04-2005, 22:23:59
RoundTo está disponible al menos a partir de Delphi 6 en la unidad Math.

Supongo, aunque no tengo forma de probarlo, que esta unidad puede integrarse a proyectos de versiones inferiores de delphi (al menos de d4 en adelante).

Hasta luego.

;)

Lepe
29-04-2005, 09:37:08
Tal como dice la ayuda de delphi 6 para RoundTo:
Note: The behavior of RoundTo can be affected by the Set8087CW procedure or SetRoundMode function.

Por tanto, para obtener el valor correcto, tenemos que poner en algun lugar de la aplicación:

SetRoundMode(rmup);

Y ahora si:

edit6.Text:= FloatToStr(roundto(1.245,-2)); // obtines 1.25

Aunque he notado que se pueden perder millonésimas de euro. En cantidades de 3.000 € se ve un fallo de 1 centimo.

Un saludo

fjardelphi
29-04-2005, 09:47:01
Gracias por el empeño.
Pero el problema lo tengo en el campo agregado. ¿Alguién utiliza un campo agregado para calcular el total de un conjunto de lineas de detalle con descuentos? Utilizando la función RoundTo y creando una función propia que calcule el total el problema está resuelto, pero creo que es más cómodo y elegante el uso de un campo agregado (si hay alguna manera de hacerlo, claro)
Saludos.