如何在shell中将科学记数法的值转换为十进制数? (首选C壳)
另外我想将它从 e-12 转换为 e-9 然后 shell
42.53e-12 至 0.04253。我必须这样做以获得一个列表。
答案1
printf
会从 shell 为你做这件事。
$ FOO=42.53e-12
$ BAR=$(printf "%.14f" $FOO)
$ echo $BAR
0.00000000004253
$
在古代+神秘的 C-shell 中,这就是。
$ set FOO=42.53e-12
$ set BAR=`printf "%.14f" $FOO`
$ echo $BAR
0.00000000004253
$
答案2
壳
许多 shell(特别是古老的+神秘的 csh)不理解浮点运算。
在大多数 shell 中都有一个printf
可以理解“科学格式”的内置函数。
$ printf '%5.0f\n' '1e3'
1000
但所有 printf 都可以不是做数学:
$ printf '%5.0f\n' '1e3+1e3'
printf: ‘1e3+1e3’: value not completely converted
对于 csh,有一个分两步解决的方法。 - 首先
将数字转换为小于 18 位的小数(对于 64 位浮点数的 53 位有效位)[a]:
% printf "%.18f\n" "42.53e-12"
0.000000000042530000
第二次
乘以1e3
(根据您的要求)并再次打印:% printf '%.15f\n' "`printf "%.18f" "42.53e-12"`e3" 0.000000042530000
当然,printf
incsh
是一个具有自己的浮点大小(64 位?)的外部实用程序,并且对于不同的操作系统可能有所不同。
数学工具。
做数学(除了 shell 之外)很自然地会想到bc
,但是 bc 有其自身的局限性(不理解e
作为指数,它必须转换为10^
)。读这个。
但 awk 可以做到:
% echo 42.53e-12 | awk '{printf("%.15f\n", $1*1e3)}'
0.000000042530000
不要期望超过 15 个正确数字,因为 awk 使用 53 位有效位。要获得更多,您需要 GNU 版本的 awk,其中编译有任意精度模块。
% echo 42.53e-12 | awk -M -v PREC=134 '{printf("%.40g\n", $1*1e3)}'
4.253e-08
即 134 个二进制位(最多)40 个十进制数字。作为小数:
% echo 42.53e-12 | awk -M -v PREC=134 '{printf("%.40f\n", $1*1e3)}'
0.0000000425300000000000000000000000000000
列表
在你的问题中,你说:
我必须这样做以获得一个列表。
但没有详细说明它是什么类型的列表。如果列表位于文件内(不是作为 shell 变量),则除了执行以下命令外,您不需要csh
(或任何其他 shell)执行任何操作:
% awk '{printf("%.15f\n", $1*1e3)}' <file
与上述相同的精度限制仍然适用。
[A]实际上,从技术上讲,您应该首先限制 printf 格式的位数%g
,因此迂腐的正确解决方案是三级转换。
在任何合理的 shell(ksh、bash、zsh)中,这都可以工作:
$ bash -c 'printf "%.15f\n" "$(printf "%.18f" "$( printf "%.18g" "42.53e-12")" )e3"'
0.000000042530000
但是在 csh 中引用 double` `
确实很尴尬,并且 csh 用于set
分配给变量。简而言之,这适用于csh
:
$ csh -c 'set a=`printf "%.18g" "42.53e-12"`; set a=`printf "%.18f" "$a"`; printf "%.18f\n" "${a}e3"'
0.000000042530000000
但是,我真的真的!认为你应该避免 csh。
答案3
您可以尝试以下操作:
echo "3.0000000000e+02" | awk '{printf("%d",$0);}'
或者如果您希望有小数
echo ""3.676361000e+02" | awk '{printf("%0.2f",$0);}'
答案4
可能不是最好的解决方案,但我设法通过一点技巧做到了。你可以做这样的事情 -
scientific='42.53e-12'
base=$(echo $scientific | cut -d 'e' -f1)
exp=$(($(echo $scientific | cut -d 'e' -f2)*1))
converted=$(bc -l <<< "$base*(10^$exp)")
>> .00000000004253000000