Para mayor precisión con (GNU) awk (con bignum compilado) use:
$ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18f\n", $1)}'
0.497043686535481300
El PREC = 100 significa 100 bits en lugar de los 53 bits predeterminados.
Si ese awk no está disponible, use bc
$ echo '0.4970436865354813*1.1' | bc -l
.54674805518902943
O necesitará aprender a vivir con la imprecisión inherente de los flotadores.
En sus líneas originales hay varios problemas:
- Un factor de 1.1 es un aumento del 10%, no del 1% (debería ser un multiplicador de 1.01). Usaré el 10%.
CONVFMT proporciona el formato de conversión de una cadena a un número (flotante). Su valor predeterminado es %.6g
. Eso limita los valores a 6 dígitos decimales (después del punto). Eso se aplica al resultado del cambio de gsub de $1
.
$ a='0.4970436865354813'
$ echo "$a" | awk '{printf("%.16f\n", $1*1.1)}'
0.5467480551890295
$ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16f\n", $1)}'
0.5467480000000000
El formato printf g
elimina los ceros finales:
$ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16g\n", $1)}'
0.546748
$ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17g\n", $1)}'
0.54674800000000001
Ambos problemas podrían resolverse con:
$ echo "$a" | awk '{printf("%.17g\n", $1*1.1)}'
0.54674805518902947
O
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17f\n", $1)}'
0.54674805518902947
Pero no tenga la idea de que esto significa mayor precisión. La representación interna del número sigue siendo flotante en tamaño doble. Eso significa 53 bits de precisión y con eso solo puede estar seguro de 15 dígitos decimales correctos, incluso si muchas veces hasta 17 dígitos parecen correctos. Eso es un espejismo.
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30f\n", $1)}'
0.546748055189029469325134868996
El valor correcto es:
$ echo "scale=18; 0.4970436865354813 * 1.1" | bc
.54674805518902943
Que también podría calcularse con (GNU) awk si la biblioteca bignum se ha compilado en:
$ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30f\n", $1)}'
0.497043686535481300000000000000