Perl浮点数四舍五入与墨西哥式数字格式化实现及优化问询
问题描述
- 我需要对MySQL查询返回的数值结果执行四舍五入操作,目前未找到符合正确舍入逻辑的现成方案,直接截断不属于我认可的正确舍入实现方式。
- 我自行编写了相关代码,可实现浮点数四舍五入功能,同时支持墨西哥西班牙语区的数字格式化规则:千位、百万位等位级使用逗号作为分隔符,例如1425可格式化为1,425。
- 我清楚这套代码执行效率较低,但可以正确实现预期功能。如果有相关优化建议,欢迎告知以提升代码运行效率。
- 提前说明:代码中的变量名和注释使用了西班牙语,还请见谅,我是墨西哥开发者 ;)
实现代码
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
内容的提问来源于stack exchange,提问作者Augusto Ayala Ledesma
相关产品推荐
相关产品推荐

