如何保留n位小数?

Ann*_*364 0 text-processing numeric-data text-formatting

我有一个包含 40,000 行的文件

head flower_all

    0.992957746478873 0.00704225352112677
    0.646410833917366 0.353589166082634
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.5 0.5
Run Code Online (Sandbox Code Playgroud)

我只想保留 3 位有效数字。我想要的输出:

0.992 0.007
0.646 0.353
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.5 0.5
Run Code Online (Sandbox Code Playgroud)

我该怎么做?

Kus*_*nda 8

awk

awk '{ printf("%.3g %.3g\n", $1, $2) }' file
Run Code Online (Sandbox Code Playgroud)

使用给定的数据,这会产生

0.993 0.00704
0.646 0.354
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.5 0.5
Run Code Online (Sandbox Code Playgroud)

请注意,0.00704 有五个小数,但有三个有效数字。

如果您只需要三位小数,请使用%.3f代替%.3g并得到

0.993 0.007
0.646 0.354
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.500 0.500
Run Code Online (Sandbox Code Playgroud)

可以使用 GNU 将上述两个变体推广到可变数量的列awk

awk -v CONVFMT='%.3g' '{ for (i=1; i<=NF; ++i) $i+=0; print }' file
Run Code Online (Sandbox Code Playgroud)

循环$i+=0强制awk将每个字段的值重新格式化为浮点数,它会在考虑CONVFMT到的情况下进行(它或多或少会等效于$i=sprintf(CONVFMT, $i))。


如果你想削减数字:

awk '{ for (i=1; i<=NF; ++i) $i=sprintf("%.5s", $i); print }' file
Run Code Online (Sandbox Code Playgroud)

这将数字视为字符串并在五个字符(假设所有数字都小于 10 且大于零)之后将它们截断,生成

0.992 0.007
0.646 0.353
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.5 0.5
Run Code Online (Sandbox Code Playgroud)

对于稍微更一般的数字切割:

awk '{ for (i=1; i<=NF; ++i) if (match($i,".*\\.[0-9]?[0-9]?[0-9]?")) $i=substr($i,RSTART,RLENGTH); print }' file
Run Code Online (Sandbox Code Playgroud)

循环中的操作在给定的正则表达式匹配结束(如果匹配)的点处削减数字。