我想在bash中将变量舍入到最接近的0.5位小数。
例如,1.3应该是1.5,1.15应该是1,2.8应该是3等等......
答案 0 :(得分:2)
仅限Bash(不调用bc
或其他外部计算器),支持带或不带符号的各种十进制数,带或不带整数部分以及有或没有小数部分:
function roundhalves () {
[[ $1 =~ ^([\+-]?)([0-9]*)\.([0-9]+)$ ]] || { printf "%s\n" "$1" && return; }
s=${BASH_REMATCH[1]}
a=${BASH_REMATCH[2]}
(( b = 1${BASH_REMATCH[3]} * 2 ))
[[ $b =~ ^([0-9][0-9])[0-9]*$ ]] && b=${BASH_REMATCH[1]}
(( b < 25 ? (b = 0) : b >= 35 ? (a += 1, b = 0) : (b = 5) ))
printf "%s%s.%d\n" "$s" "$a" "$b"
}
注意:算法很简单:取小数部分,前置1,乘以2并保持两个前(最左)数字。结果整数在[20..39]
范围内。与25和35比较。
注意:舍入是无穷大但这很容易修改。
注意:这受到最大可表示数字(64位体系结构上的[-2**63..2**63-1]
)的限制。 bc
没有此限制。如果您的数字在整数或小数部分中可能有很多(超过18个)数字,并且如果您有数字,则更喜欢bc
。
答案 1 :(得分:1)
这可能是一种更简单的方法,但这应该有效:
echo "1.3 * 2" | bc | xargs -I{ printf "%1.f" { | xargs -I% echo "% * .5" | bc
#1.5
echo "1.15 * 2" | bc | xargs -I{ printf "%1.f" { | xargs -I% echo "% * .5" | bc
#1.0
echo "2.8 * 2" | bc | xargs -I{ printf "%1.f" { | xargs -I% echo "% * .5" | bc
#3.0
所以你在这里改变的唯一事情是回声值的第一个数字。如果你想要一个功能......
function roundhalves { echo "$1 * 2" | bc | xargs -I@ printf "%1.f" @ | xargs -I% echo "% * .5" | bc }
就这样称呼它:
roundhalves 1.3
roundhalves 1.15
roundhalves 2.8
答案 2 :(得分:0)
这是一个原始答案,它由@CharlesDuffy对接受的答案留下了非常有用的评论。唯一的不同是,我删除了这里的字符串,以便可以在sh和bash上使用此功能。
roundhalves() {
printf '%s * 0.5\n' "$(printf '%1.f' "$(printf '%s * 2\n' "$1" | bc)")" | bc
}
只是认为这对尝试编写可移植脚本的人可能有用。
答案 3 :(得分:0)
怎么样:
awk '{print int(($1+0.25)/0.5)*0.5}'.
PS。如果您想将数字四舍五入到最接近的x(例如0.1、50、100等),只需使用
awk '{print int(($1+x/2)/x)*x}'.