Gambadas: El Redondeo

Leyendo hoy en el boletín de CAMPUS MVP la gambada del mes de Mayo, he recordado que tengo en mi HD portátil una que tenía vuelto el juicio a un cliente en el que estuve trabajando, ya que al cerrar la caja del mes, no cuadraba la facturación de las cuentas de ventas al contado (Unos eurillos) en las delegaciones donde estaba implantada la nueva aplicación y que a final de mes se envía a Central y se comprueba con una rutina de Oracle.

Me pidieron ayuda para solventar el problema y depurando la rutina de facturación me encontré esto:

   1:  /// <summary>
   2:  /// Trunca el número de decimales de un número al
   3:  /// indicado en el parámetro iNumDecimales
   4:  /// </summary>
   5:  /// <param name="dNumero">Numero a truncar</param>
   6:  /// <param name="iNumDecimales">Nº de decimales</param>
   7:  /// <returns></returns>
   8:  public double Redondear(double dNumero, int iNumDecimales)
   9:  {
  10:      try
  11:      {
  12:          string sTodo, sParteEntera, sParteDecimal;
  13:          string[] sNumero;
  14:          sTodo = dNumero.ToString();
  15:   
  16:          /* Si el número tiene parte decimal.*/
  17:          if (sTodo.IndexOf(".") != -1)
  18:          {
  19:              sNumero = sTodo.Split('.');
  20:   
  21:              sParteEntera = sNumero[0];
  22:              sParteDecimal = sNumero[1];
  23:   
  24:              if (sParteDecimal.Length > iNumDecimales)
  25:                  sParteDecimal = sParteDecimal.Remove(iNumDecimales, 
  26:                      sParteDecimal.Length - iNumDecimales);
  27:   
  28:              sTodo = sParteEntera + "." + sParteDecimal;
  29:          }
  30:          dNumero = double.Parse(sTodo);
  31:          return dNumero;
  32:      }
  33:      catch(Exception _ex)
  34:      {
  35:          throw new ...(_ex,"Factura","Redondear");
  36:      }
  37:  }

La solución fue sencilla:

   1:  /// <summary>
   2:  /// Trunca el número de decimales de un número al
   3:  /// indicado en el parámetro iNumDecimales
   4:  /// </summary>
   5:  /// <param name="dNumero">Numero a truncar</param>
   6:  /// <param name="iNumDecimales">Nº de decimales</param>
   7:  /// <returns></returns>
   8:  public decimal Redondear(decimal dNumero, int iNumDecimales)
   9:  {
  10:      return Math.Round(dNumero, iNumDecimales);
  11:  }

Salu2

Published 16/5/2007 9:45 por Luis Ruiz Pavón
Archivado en:

Comentarios

# re: Gambadas: El Redondeo

No está mal utilizar la función Math.Round si no fuera que funciona mal, sino comprueba los siguientes resultados:

? math.Round(1.15,1)

1.2

? math.Round(1.35,1)

1.4

? math.Round(1.25,1)

1.2    <---- el resultado debería ser 1.3

Yo he creado la siguiente función para el redondeo:

Shared Function RedondeoDecimal(ByVal dValor As Decimal, Optional ByVal iDecimales As Integer = 2) As Decimal

       Dim dValor2 As Decimal

       If dValor < 0 Then

           dValor2 = -dValor * (10 ^ iDecimales)

           Return -Int(dValor2 + 0.5) / (10 ^ iDecimales)

       Else

           dValor2 = dValor * (10 ^ iDecimales)

           Return Int(dValor2 + 0.5) / (10 ^ iDecimales)

       End If

   End Function

Wednesday, May 16, 2007 10:07 AM by J.A.P.S.

# re: Gambadas: El Redondeo

A ver hombre... J.A.S.P como puedes decir que 'redondea mal', crees realmente que puede tener un error en ese código sin arreglar?? Lo que pasa es que estás redondeando con la norma de IEEE, es decir como dictan los estándares. En esa norma, que por cierto es la más justa ( y no la enseñan en la escuela )  se comporta de diferente forma en los impares que los pares, de hay que 1.15 y 1.35 suban a 1.2 y 1.4 y los pares como 1.25 bajen a 1.2.

Si quieres usar la menos justa, y la que seguramente te enseñaron en la escuela puedes usar una de las sobrecargas de Math.Round.

Saludos

Unai

Wednesday, May 16, 2007 10:28 AM by Unai

# re: Gambadas: El Redondeo

Hola,

La función Math.Round no está mal J.A.P.S.

Como sabrás hay distintos tipos de redondeo. El que usa por defecto la función Math.Round es el redondeo al "par más próximo" que es el más comunmente aceptado.

En este tipo de redondeo, cuando pides redondear a 1 dígito decimal 1.25 te encuentras a igual distancia de 1.3 y 1.2 que son los números de 1 dígito decimal más próximos. Por lo tanto se aplicar la regla del "par más próximo", que consiste en quedarse con el número par más próximo, en este caso el 1.2. Si lo probases con 1.35 te devolvería 1.4.

Este es el método de redondeo más justo ya que cuando se produce una situación de igual distancia algunas veces se redondeará al alza y otras a la baja. Y además suele ser el obligatorio en algunos ámbitos.

De todas formas, si quieres utilizar otro tipo de redondeo, la función Math.Round tiene una sobrecarga que admite un tercer parámetro que es una enumeración indicando el tipo de redondeo. Con eso ya podrás hacer el redondeo que buscas que se conoce como el "más lejano a cero".

Un saludo

Wednesday, May 16, 2007 10:34 AM by Marco Amoedo

# re: Gambadas: El Redondeo

No puede estar mejor explicado Marco.

Sólo puntualizar que la sobrecarga de Math.Round se ha añadido en NET 2.0.

Salu2

Wednesday, May 16, 2007 10:38 AM by Luis Ruiz Pavón

# re: Gambadas: El Redondeo

buenas Luis! Yo tambien me rei de lo lindo con el ejemplo de Jose en el boletin de CampusMVP (llevaba unos dias sin leer worsethanfailure.com, y me volvieron las ganas!) }:D

muy buenos Unai y Marco en sus explicaciones sobre la norma IEEE... no hay nada como tener a un monton de crases para contestar los comentarios }:)

Nos veremos en el CodeCamp este mes?

Wednesday, May 16, 2007 1:43 PM by phobeo

# re: Gambadas: El Redondeo

hola phobeo! La verdad es que la gambada es la leche y para serte sincero desconocía la página y hoy me he reido de lo lindo con las gambadas allí publicadas XD

Perdón, se me olvidó mencionar a Unai un crash de las Matemáticas XD

Salu2

Wednesday, May 16, 2007 2:41 PM by Luis Ruiz Pavón

# re: Gambadas: El Redondeo

Jejeje, nunca te acostarás sin saber algo nuevo. Jejeje

Wednesday, May 16, 2007 10:08 PM by Eugenio Estrada

# re: Gambadas: El Redondeo

Comparto lo dicho por Eugenio.. =)

Saludos

Thursday, May 17, 2007 5:31 AM by Christian Quintana

# re: Gambadas: El Redondeo

No tenía conocimiento de la sobrecarga de Math.Round posiblemente porque cuando programe esta funcionalidad lo hice en VB 6.0 y en la versión .NET 1.1. Aunque la forma correcta del redondeo sea la norma de IEEE, la mayoria de las empresas utilizan el sistema del redondeo más cerca del 0.

Muchas gracias

Thursday, May 17, 2007 9:11 AM by J.A.P.S.

# re: Gambadas: El Redondeo

Hola,

En cualquier caso, creo q en tu código hay un mal de raíz que consiste en utilizar el tipo double para representar cantidades monetarias, más propio de lenguajes de generación anterior que no estaban pensados para ser utilizados para cálculos financieros (por ejemplo Pascal)...

.NET nos ofrece System.Decimal para eso.

Saludos - Octavio

Thursday, May 17, 2007 12:20 PM by Octavio Hernández

# re: Gambadas: El Redondeo

Pues tienes toda la razón Octavio, pero eso ya lo modifiqué en su día, como dije la tenía en el HD portátil y no lo actualicé, lo cambio.

Gracias!!!

Thursday, May 17, 2007 6:09 PM by Luis Ruiz Pavón

# re: Gambadas: El Redondeo

hi, me he reido mucho con esto, quise publicarlo en mi blog, espero no sea molestia, y si es asi me lo hacen saber y lo borrare, claro pondre la fuente, bye cuidense y estare por aca mas seguido

Saturday, June 23, 2007 2:14 AM by Victor Tasayco

Deja tu comentario

(requerido) 
(requerido) 
(opcional)
(requerido)