如何修改浮点数以显示至少 n 位数字
How to modify a float to display at least n digits
在 bash 中,如何修改 float
以使点之前的部分至少有两位数?
我想让 A 列 中的数字显示为 B 列:
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.19
3.5 03.5
我做了很多搜索,但我发现的大部分内容都在谈论如何显示带有 N 小数位的数字(例如 17.7647 to 17.76
),这没有任何帮助.
how can I modify a float so that the part coming before the dot is having at least two digits.
没有实用程序 - 编写您自己的代码来执行此操作。你会:
- 计算逗号前的位数
- 如果位数小于2
- 如果位数是1
- 前加一个零
- 如果为零
- 添加两个前导零
我还可以看到 sed
有两个表达式,每个表达式都与正则表达式匹配逗号前的位数。
这是 bash
中的实用函数,使用 printf
实现此目的:
fpad() {
local n="${1?needs an argument}"
[[ $n == [0-9].* ]] && echo "0$n" || echo "$n"
}
用作:
fpad "8.456"
08.456
fpad "4.19"
04.19
fpad "3.5"
03.5
fpad "13.25"
13.25
fpad "1325"
1325
将 Glen 的建议与 read
结合使用:
fpad() {
local n="${1?needs an argument}"
local num frac
IFS=. read num frac <<< "$n"
printf '%02d.%d\n' "$num" "$frac"
}
您可以扩展一点,通过允许设置实部和小数部分的宽度并完全验证输入并处理任何错误,进一步扩展 @anubhava 的好答案在你的功能中。虽然方法是相同的,但使用 printf
格式字符串是关键。
例如,您的函数可以将浮点数作为第一个参数,将实部的宽度作为第二个参数,并可选择将小数部分的宽度作为第三个参数,例如
#!/bin/bash
formatfloat () {
[ -z "" -o -z "" ] && { ## validate at least 2 arguments given
printf "error: formatfloat() insufficient arguments.\n" >&2
printf "usage: formatfloat() float width_real [width_fract]\n" >&2
return 1;
}
[[ =~ ^-*[[:digit:]]*[.][[:digit:]]* ]] || { ## validate float
printf "error: formatfloat() not a valid floating point number.\n" >&2
return 1
}
[ "" -eq "" > /dev/null ] || { ## validate width is an integer
printf "error: formatfloat() width_real not an integer.\n" >&2
return 1
}
local realpart="${1%.*}" ## parameter expansion separates real/fraction parts
local fractpart="${1#*.}"
local width_real=""
if [ -n "" ]; then ## if fractional part width given
[ "" -eq "" > /dev/null ] || { ## validate it is an integer
printf "error: formatfloat() width_fract not an integer.\n" >&2
return 1
}
local width_fract="" ## output setting both widths
local fppad="$((width_fract - ${#fractpart}))" ## needed fract part rt-pad
[ "$fppad" -le 0 ] && { ## no padding needed
printf "%0*d.%d\n" $width_real $realpart $fractpart
return 0
}
for ((i = 0; i < fppad; i++)); do ## add padding to fract part
fractpart="${fractpart}0"
done
printf "%0*d.%*d\n" $width_real $realpart $width_fract $fractpart
else ## output setting real-part width
printf "%0*d.%d\n" $width_real $realpart $fractpart
fi
return 0
}
您的数据的一个简短示例可以是:
printf "A (Current) B (Desired)\n----- ------\n"
for n in 8.456 4.19 3.5; do
printf "%-14s%s\n" "$n" "$(formatfloat "$n" 2)"
done
输出
$ bash formatfloat.sh
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.19
3.5 03.5
设置两者的宽度
for n in 8.456 4.19 3.5; do
printf "%-14s%s\n" "$n" "$(formatfloat "$n" 2 3)"
done
输出
$ bash formatfloat.sh
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.190
3.5 03.500
在 bash 中,如何修改 float
以使点之前的部分至少有两位数?
我想让 A 列 中的数字显示为 B 列:
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.19
3.5 03.5
我做了很多搜索,但我发现的大部分内容都在谈论如何显示带有 N 小数位的数字(例如 17.7647 to 17.76
),这没有任何帮助.
how can I modify a float so that the part coming before the dot is having at least two digits.
没有实用程序 - 编写您自己的代码来执行此操作。你会:
- 计算逗号前的位数
- 如果位数小于2
- 如果位数是1
- 前加一个零
- 如果为零
- 添加两个前导零
- 如果位数是1
我还可以看到 sed
有两个表达式,每个表达式都与正则表达式匹配逗号前的位数。
这是 bash
中的实用函数,使用 printf
实现此目的:
fpad() {
local n="${1?needs an argument}"
[[ $n == [0-9].* ]] && echo "0$n" || echo "$n"
}
用作:
fpad "8.456"
08.456
fpad "4.19"
04.19
fpad "3.5"
03.5
fpad "13.25"
13.25
fpad "1325"
1325
将 Glen 的建议与 read
结合使用:
fpad() {
local n="${1?needs an argument}"
local num frac
IFS=. read num frac <<< "$n"
printf '%02d.%d\n' "$num" "$frac"
}
您可以扩展一点,通过允许设置实部和小数部分的宽度并完全验证输入并处理任何错误,进一步扩展 @anubhava 的好答案在你的功能中。虽然方法是相同的,但使用 printf
格式字符串是关键。
例如,您的函数可以将浮点数作为第一个参数,将实部的宽度作为第二个参数,并可选择将小数部分的宽度作为第三个参数,例如
#!/bin/bash
formatfloat () {
[ -z "" -o -z "" ] && { ## validate at least 2 arguments given
printf "error: formatfloat() insufficient arguments.\n" >&2
printf "usage: formatfloat() float width_real [width_fract]\n" >&2
return 1;
}
[[ =~ ^-*[[:digit:]]*[.][[:digit:]]* ]] || { ## validate float
printf "error: formatfloat() not a valid floating point number.\n" >&2
return 1
}
[ "" -eq "" > /dev/null ] || { ## validate width is an integer
printf "error: formatfloat() width_real not an integer.\n" >&2
return 1
}
local realpart="${1%.*}" ## parameter expansion separates real/fraction parts
local fractpart="${1#*.}"
local width_real=""
if [ -n "" ]; then ## if fractional part width given
[ "" -eq "" > /dev/null ] || { ## validate it is an integer
printf "error: formatfloat() width_fract not an integer.\n" >&2
return 1
}
local width_fract="" ## output setting both widths
local fppad="$((width_fract - ${#fractpart}))" ## needed fract part rt-pad
[ "$fppad" -le 0 ] && { ## no padding needed
printf "%0*d.%d\n" $width_real $realpart $fractpart
return 0
}
for ((i = 0; i < fppad; i++)); do ## add padding to fract part
fractpart="${fractpart}0"
done
printf "%0*d.%*d\n" $width_real $realpart $width_fract $fractpart
else ## output setting real-part width
printf "%0*d.%d\n" $width_real $realpart $fractpart
fi
return 0
}
您的数据的一个简短示例可以是:
printf "A (Current) B (Desired)\n----- ------\n"
for n in 8.456 4.19 3.5; do
printf "%-14s%s\n" "$n" "$(formatfloat "$n" 2)"
done
输出
$ bash formatfloat.sh
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.19
3.5 03.5
设置两者的宽度
for n in 8.456 4.19 3.5; do
printf "%-14s%s\n" "$n" "$(formatfloat "$n" 2 3)"
done
输出
$ bash formatfloat.sh
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.190
3.5 03.500