Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Redondeo (https://www.clubdelphi.com/foros/showthread.php?t=2643)

cesar vidal 31-07-2003 16:52:25

Redondeo
 
Hola amigos del foro, Tengo problemas para redondear una cifra con tres decimales a 2, en este caso especifico es el número
21,465 q debería darme 21,47 al redondearlo, pero me da como resultado el 21,46. A ver si me dan una ayuda.

Gracias anticipadamente

Cesar

marcoszorrilla 31-07-2003 22:22:17

Prueba con esta función que cree en su momento para el Euro.

Código:


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.

cesar vidal 03-08-2003 07:55:06

Marcos, agradesco tu respuesta que fue la indicada para resolver el problema.

saludos

roman 03-08-2003 08:25:38

¿No es más fácil así?

Código:

var
  X: Double;

begin
  X := 21.465;
  SetRoundMode(rmDown);
  Caption := FloatToStr(SimpleRoundTo(X, -2)); // Imprime 21.47

// Saludos

marcoszorrilla 05-08-2003 12:36:16

Hola Roman:

Sabes si funciona con todas las versiones de Delphi, estoy en Francia y no puedo hacer comprobaciones

delphi.com.ar 05-08-2003 15:41:17

Es a partir de Delphi 6.

Saludos!

Crashthebig 15-04-2009 20:15:14

es muy simple el redondeo solo debes incluir en la seccion uses la libreria math y utilizar la funcion SimpleRoundTo().
Esta funcion te permite redonder un numero de la siguiente forma:

SimpleRoundTo(1234567, 3) 1234000
SimpleRoundTo(1.234, -2) 1.23
SimpleRoundTo(1.235, -2) 1.24
SimpleRoundTo(-1.235, -2) -1.23
ej:
Código Delphi [-]var a,b,c:real begin a:=strtofloat(edit1.text); b:=strtofloat(edit2.text); c:=a/b; edit3.text:=floattostr(SimpleRoundTo(c,-2));

este codigo lo que hace es que hacer una division de dos numeros reales y formatea la salida para que el resultado de la division solo tenga dos cifras decimales ej:
53/3=17,6666666666667;
pero con simpleroundto:
53/3=17.67

rgstuamigo 15-04-2009 20:58:05

Mira aqui;)

novato_erick 03-04-2014 03:32:30

Siguiendo este post que tiene muchos años ya sin embargo me esta pasando algo curioso respecto al redondeo con la función
Código Delphi [-]
 function SimpleRoundTo(variable, -2)
//Resultado en una suma de 11.21 + 0.78 = 11.99 con la función me redondea a 12.00

En este caso como verán ese centavo me está causando diferencia en el desarrollo que estoy realizando mucha diferencia a la hora de los reportes de ventas.

Alguna mejor idea de funciones que me retorne valores deseados reales... espero alguna gran ayuda...


Saludos


novato_erick

Casimiro Notevi 03-04-2014 09:30:02

¿Y cual es el problema?

ecfisa 03-04-2014 10:12:11

Hola novato_erick.

A mi tampoco me queda claro si lo que esperas es 11.99 y obtenes 12 o viceversa.

El método común de redondeo consiste en verificar el valor del próximo dígito a la derecha del que se quiere redondear. Si este es menor a 5, el dígito a redondear no se altera, caso contrario se incrementa su valor en uno.

Si el valor a redondear a dos cifras es 11.99, entonces:
Código Delphi [-]
  Resultado:= SimpleRoundTo(11.99); // el segundo parámetro es -2 por defecto
dejará en la variable "Resultado" el valor 11.99, para hacerlo mas claro agreguemos un cero a la derecha: 11.990. Como queremos redondear a dos cifras, revisamos el valor de la tercera (0), es menor que cinco y por tanto no se tiene que alterar el valor de la segunda.

Para lograr el resultado 12 a partir de 11.99 habría que hacer:
Código Delphi [-]
Resultado:= SimpleRoundTo(11.99, -1);

Si estas obteniendo otro comportamiento, sinceramente no sé que puede estar pasando...

Saludos :)

novato_erick 03-04-2014 14:12:04

Hola ecfisa y casimiro gracias ppr responder... en realidad ecfisa tine razon. El problema no esta en las funciones de redondeo si no en el mismo campo en la base de datos de firebird q almacena el dato como un float hasta con N cantidad de decimales q en ocasiones en el tercer decimal hay un numero mayor de 5 haciendo dificil o creo imposible q no me redondee... tendre q cambiar el campo en la bd a Decimal 12,2..

....

Agradeciendo siempre su aporte


Novato_erick

Casimiro Notevi 03-04-2014 15:54:56

Cita:

Empezado por novato_erick (Mensaje 474758)
Hola ecfisa y casimiro gracias ppr responder... en realidad ecfisa tine razon. El problema no esta en las funciones de redondeo si no en el mismo campo en la base de datos de firebird q almacena el dato como un float hasta con N cantidad de decimales q en ocasiones en el tercer decimal hay un numero mayor de 5 haciendo dificil o creo imposible q no me redondee... tendre q cambiar el campo en la bd a Decimal 12,2..

Claro, pero eso es así en todos los sistemas, no puedes usar un float para eso.

ecfisa 03-04-2014 15:58:24

Hola.

Si, y también agregar que podes utilizar la función ROUND de Firebird.

Como ejemplo:
Código SQL [-]
SELECT ROUND(3.141592654, 6) FROM RDB$DATABASE; -- 3,141593000

Saludos :)

novato_erick 03-04-2014 16:57:38

Cita:

Casimiro:
Claro, pero eso es así en todos los sistemas, no puedes usar un float para eso
Es cierto a duro golpe me acabo de percatar de eso..

Cita:

Si, y también agregar que podes utilizar la función ROUND de Firebird.

Como ejemplo:
Código SQL [-]
SELECT ROUND(3.141592654, 6) FROM RDB$DATABASE; -- 3,141593000

acabo de intentarlo con tu sugerencia ecfisa, pero el resultado es el mismo ejemplo:
Código SQL [-]
SELECT ROUND(11.9954967498779, 6) FROM RDB$DATABASE; -- 11.995496

el asunto como lo mencioné antes la db tiene el campo de tipo Float el cual todo numero que ingrese me manda hasta doce decimales.

la solución creo que estaría en cambiar el tipo de dato a Decimal 12, 2 como lo puse en el post anterior sin embargo me acabo de encontrar que no es compatible Decimal con float En firebird aunque tambien se que no es exclusivo de firebird la incopatibilidad de datos ya ingresado para codificar el campo;

nuevamente Gracias Chicos... Es bueno saber que no estoy solo en esto....

Saludos

ecfisa 03-04-2014 17:21:29

Cita:

Empezado por novato_erick (Mensaje 474762)
...
acabo de intentarlo con tu sugerencia ecfisa, pero el resultado es el mismo...

Si si, por supuesto. Funciona del mismo modo que SimpleRoundTo, solo lo mencioné como alternativa para, por ejemplo, traer el resultado ya redondeado desde la consulta.

Como te comentó Casimiro es el comportamiento natural de todos los sistemas (al menos los que conozco).

Saludos :)

nlsgarcia 03-04-2014 21:55:38

novato_erick,

Cita:

Empezado por novato_erick
...Alguna mejor idea de funciones de redondeo que me retorne valores deseados reales... :confused:

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

interface

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

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   RadioGroup1.ItemIndex := 0;
end;

// Realiza diversos tipos de redondeo
procedure TForm1.Button1Click(Sender: TObject);
var
   N1 : Double;
   E : Integer;

begin

   {

   -function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode
  
   Sets the FPU rounding mode.
  
   (RoundMode)
   rmNearest : Rounds to the closest value.
   rmDown : Rounds toward negative infinity.
   rmUp : Rounds toward positive infinity.
   rmTruncate : Truncates the value, rounding positive numbers down and negative numbers up.
  
   -function RoundTo(const AValue: Double; const ADigit: TRoundToRange): Double;
  
   Rounds a floating-point value to a specified digit or power of ten using “Banker’s rounding”.

   }

   N1 := 2.718281;

   case RadioGroup1.ItemIndex of

      0 : begin
             SetRoundMode(rmUp);
             // Muestra 2.72
             ShowMessage(FormatFloat('#,###,###.00',RoundTo(N1,-2)));
          end;

      1 : begin
             SetRoundMode(rmDown);
             // Muestra 2.71
             ShowMessage(FormatFloat('#,###,###.00',RoundTo(N1,-2)));
          end;

      2 : begin
             SetRoundMode(rmNearest);
             // Muestra 2.72
             ShowMessage(FormatFloat('#,###,###.00',RoundTo(N1,-2)));
          end;

      3 : begin
             SetRoundMode(rmTruncate);
             // Muestra 2.71
             ShowMessage(FormatFloat('#,###,###.00',RoundTo(N1,-2)));
          end;

   end;

end;

// Estable el número de decimales (Truncado) sin redondeo de valores doubles
function DoubleDecimals(Number : Double; Decimal : Integer) : Double;
var
   AuxNumber : String;

begin

   AuxNumber := FloatToStr(Number);

   if Pos('.',AuxNumber) > 0 then
      Result := StrToFloat(Copy(AuxNumber,1,Pos('.',AuxNumber) + Decimal))
   else
   if Pos(',',AuxNumber) > 0 then
      Result := StrToFloat(Copy(AuxNumber,1,Pos(',',AuxNumber) + Decimal))
   else
      Result := Number;

end;

// Convierte un valor de n decimales a m decimales sin redondeo
procedure TForm1.Button2Click(Sender: TObject);
var
   N1 : Double;
   E : Integer;

begin

   N1 := 2.718281;

   // Convierte 2.718281 en 2.71, se establece el truncado de decimales sin redondeo a 2
   N1 := DoubleDecimals(N1,2);

   // Muestra 2.71
   ShowMessage(FloatToStr(N1));

end;

end.
El código anterior permite hacer diferentes tipos de ajustes decimales con redondeo y sin redondeo.

Espero sea útil :)

Nelson.

Casimiro Notevi 03-04-2014 22:04:22

Si quieres redondear, por ejemplo, a 2 decimales:
Código Delphi [-]
resultado := redondeo(importe,2);
Código Delphi [-]
uses Math;

...
...

function Redondeo (valor: Double; decimales: integer = 0): Double;
var
  factor: Double;
begin
  factor := IntPower(10,decimales);
  //
  if valor > 0 then
    Result := (trunc((valor*factor)+0.5)) / factor
  else
    Result := (trunc((valor*factor)-0.5)) / factor;
end;

ecfisa 04-04-2014 02:17:44

Hola novato_erik.

Tanto Delphi como Firebird, redondean (y lo hacen muy bién) con SimpleRoundTo() y ROUND(), pero si sos de los que te gusta ir a las bases, te pongo otra opcion.

Delphi:
Código Delphi [-]
function Redondear(const Numero: Double; const Digitos: Integer): Double;
var
  Factor: Double;
begin
  Factor:= Abs(Exp(Ln(10)*(-Digitos)));
  Result:= Trunc((Numero/Factor) + 0.5) * Factor;
end;

Firebird:
Código SQL [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE SP_ROUND(NUMERO DOUBLE PRECISION, DIGITOS INTEGER)
RETURNS(RESULT DOUBLE PRECISION)
AS
  DECLARE VARIABLE FACTOR DOUBLE PRECISION;
BEGIN
  FACTOR = ABS(EXP(LN(10)*(-DIGITOS)));
  RESULT = TRUNC((NUMERO/FACTOR)+0.5)*FACTOR;
  SUSPEND;
END^

SET TERM ; ^

Saludos :)

novato_erick 21-04-2014 18:04:11

Hola chicos definitivamente cambié en la base de datos en firebird el tipo de campo a decimal 12,2 corrigió muchos de mis problemas pero como dije muchos de mis problemas quedando algunos al azar en la aplicación con el asunto de los redondeos.

nuestro amigo ecfisa me dice:

Cita:

Tanto Delphi como Firebird, redondean (y lo hacen muy bién) con SimpleRoundTo() y ROUND()
lo hice y como respaldo busqué la ayuda de Delphi y salió esto:

Cita:

function SimpleRoundTo(const AValue: Single; const ADigit: TRoundToRange = -2): Single;
function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
function SimpleRoundTo(const AValue: Extended; const ADigit: TRoundToRange = -2): Extended;

SimpleRoundTo(1234567, 3)
1234000

SimpleRoundTo(1.234, -2)
1.23

SimpleRoundTo(1.235, -2) //este redondeo es que me interesa
1.24

SimpleRoundTo(-1.235, -2)
-1.23

en fin a la hora de utilizar la función me sale 5.26 en vez de5.27

Código Delphi [-]
 5.26 := simpleroundto(5.265, -2)

en fin necesito esto porque en mi país están utilizando las dichosas impresoras fiscales el cual ese valor de 5.265 ella misma me hace el calculo y lo guarda como 5.27 mientras que en la aplicación simpre me está mostrando el 5.26 aun utilizando la función Simpleroundto.

Saludos


La franja horaria es GMT +2. Ahora son las 13:35:59.

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