在bash中舍入到最接近的0.5小数

时间:2017-10-31 03:15:30

标签: bash

我想在bash中将变量舍入到最接近的0.5位小数。

例如,1.3应该是1.5,1.15应该是1,2.8应该是3等等......

4 个答案:

答案 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}'.