I had to round numbers that are a result of MySQL Querys. I didn't find a good solution for rounding in the correct way (truncating is not the correct way in my opinion).
I wrote this code that rounds float numbers and also formatted the numbers in the Spanish-Mexican way (using comma as a thousands, millions, etc.. (like 1425 -> 1,1425)
I know it is very inefficient, but it does the work in the right way. If you have any suggestions please let me know to make it more efficient.
Sorry for the Spanish variables and comments.. I'm Mexican!!! ;)
sub formatea_numero # recibe una cifra sin formato y le agrega comas por cada 3 digitos
{
my($importe_orig,$dec_a_redondear) = @_;
my @digitos_corregido;
my $contador=0;
my $signo;
my $importex;
my $decimal_con_ceros_al_inicio = 0;
### SIGNO ######################
### Obteniendo el signo si lo tiene
if($importe_orig=~/([-|+])(.*)/) # SI TIENE SIGNO $1 EL NUM ES $2
{
$signo = $1;
$importex = substr $importe_orig, 1;
}
else # NO TIENE SIGNO EL NUM ES $importe_orig
{
$importex = $importe_orig;
}
### DECIMALES ################
### Si tiene decimales.. se obtiene la parte entera y la parte decimal
if($importex=~/\./) # Tiene decimales
{
if ($dec_a_redondear ne "" && $dec_a_redondear == 0) # Caso Especial de que son 0 decimales a redondear
{
$importex=~/(.*)\.(.)(.*)/;
$parte_entera = $1;
$primer_decimal = $2;
$resto_decimal = $3;
if ($primer_decimal >= 5)
{$parte_entera = $parte_entera+1;}
}
else
{
if($importex=~/(.*)\.(.+)/) # Parte entera $1 Parte decimal $2
{
$parte_entera = $1;
$parte_decimal = $2;
if ($parte_decimal=~/^(0+).*/ ) # Caso especial si el decimal inicia en 0 ejem 3.0015 1.0000003 1.04 etc
{
$decimal_con_ceros_al_inicio =1;
$parte_decimal = "1" . $parte_decimal;
}
}
########### REDONDEAR DECIMALES
if ($decimal_con_ceros_al_inicio)
{
$dec_a_redondear = 1 + $dec_a_redondear;
$num_decimales_original = 1+ length $parte_decimal;
}
else
{ $num_decimales_original = length $parte_decimal;}
if ($dec_a_redondear>=0 && $dec_a_redondear < $num_decimales_original)
{
$parte_decimal_1 = substr($parte_decimal,0,$dec_a_redondear); # se obtienen los digitos hasta el numero de decimales que se quiere redondear
$siguiente_decimal = substr($parte_decimal,$dec_a_redondear,1); # se obtiene el primer dígito a descartar .. si es mayor que 5 se le agrega uno al anterior digito
if($siguiente_decimal >=5)
{
$largo_inicial_parte_decimal_1 = length $parte_decimal_1;
$parte_decimal_1 = $parte_decimal_1 +1;
$largo_final_parte_decimal_1 = length $parte_decimal_1;
if($largo_final_parte_decimal_1 <= $largo_inicial_parte_decimal_1)
{
$parte_decimal = $parte_decimal_1;
}
else
{
$parte_entera = $parte_entera + 1;
$parte_decimal = $parte_decimal_1 - 1;
$parte_decimal = 0;
}
}
else
{
$parte_decimal = $parte_decimal_1;
}
} # cierra if ($dec_a_redondear>0 && $dec_a_redondear < $num_decimales_original)
if ($decimal_con_ceros_al_inicio)
{
$parte_decimal=~/^1(.+)/;
$parte_decimal = $1;
}
########### TERMINA DECIMALES (redondeando)
} # Cierra if ($dec_a_redondear ne "" && $dec_a_redondear == 0) # Caso Especial de que son 0 decimales a redondear
} # cierra if($importex=~/\./) # Tiene decimales
########### FORMATEANDO LOS MILES ###########
if($importex=~/\./) # Tiene decimales
{
@digitos = split(//,$parte_entera);
}
else # No tiene decimales
{
@digitos = split(//,$importex);
}
@digitos= reverse(@digitos);
foreach $digito(@digitos)
{
if ($contador ==3)
{
push (@digitos_corregido,",");
push (@digitos_corregido,$digito);
$contador=1;
}
else
{
push (@digitos_corregido,$digito);
$contador++;
}
}
@digitos_corregido = reverse(@digitos_corregido);
$importe2 = join('',@digitos_corregido);
### Termina de procesar la parte entera
### Se integra el signo, la parte entera formateada y la parte decimal
if($importex=~/\./)
{
if ($dec_a_redondear ne "" && $dec_a_redondear == 0)
{ $importe2 = $importe2;}
else
{
if ($parte_decimal >0)
{$importe2 = $importe2 . "." .$parte_decimal;}
else
{$importe2 = $importe2;}
}
}
if($importe_orig=~/([-|+])(.*)/)
{
$importe2 = $signo . $importe2 ;
}
return $importe2;
} # cierra sub formatea_numero # recibe una cifra sin formato y le agrega comas por cada 3 digitos