如何在Shell命令中舍入大数?

时间:2016-04-17 18:39:33

标签: shell terminal rounding

在Mac终端中,我想绕一大堆。

例如,

在10 ^ 13位:
1234567812345678 - > 12300000亿

或者在10 ^ 12位:
1234567812345678 - > 12350000亿

所以我想指定这个地方,然后得到四舍五入的数字。 我该怎么做?

3 个答案:

答案 0 :(得分:2)

您可以使用arithmetic expansion

$ val=1234567812345678
$ echo $(( ${val: -13:1} < 5 ? val - val % 10**13 : val - val % 10**13 + 10**13 ))
1230000000000000
$ echo $(( ${val: -12:1} < 5 ? val - val % 10**12 : val - val % 10**12 + 10**12 ))
1235000000000000

检查最重要的删除数字是否为5或更大,如果是,则最后一个重要的未删除数字增加1;然后我们从(可能修改的)初始值中减去除法余数。

如果您不想以这种方式编写它,可以将它包装在一个小函数中:

round () {
    echo $(( ${1: -$2:1} < 5 ? $1 - $1 % 10**$2 : $1 - $1 % 10**$2 + 10**$2 ))
}

然后可以像这样使用:

$ round "$val" 13
1230000000000000
$ round "$val" 12
1235000000000000

请注意,引用$val并非绝对必要,这只是一个好习惯。

如果单行内容过于神秘,那么这是一个更具可读性的版本:

round () {
    local rounded=$(( $1 - $1 % 10**$2 ))   # Truncate

    # Check if most significant removed digit is >= 5
    if (( ${1: -$2:1} >= 5 )); then
        (( rounded += 10**$2 ))
    fi
    echo $rounded
}

除了算术扩展之外,它还使用参数扩展来获取子字符串:${1: -$2:1}代表“从$1开始,从后面开始计数$2,取一个字符”。在-$2之前必须有一个空格(或者必须在括号中),否则它将被解释为不同的扩展,检查$1是否未设置或为空,这是我们不想要的

答案 1 :(得分:1)

awk的{​​{1}}函数可以在双精度浮点运算的范围内为你舍入:

[s]printf

对于纯$ for p in 13 12; do awk -v p="$p" '{ n = sprintf("%.0f", $0 / 10^p); print n * 10^p }' <<<1234567812345678 done 1230000000000000 1235000000000000 实施,请参阅Benjamin W.'s helpful answer

答案 2 :(得分:0)

实际上,如果你想要舍入到n位有效数字,你最好通过混合传统的数学和字符串来提供服务。

严肃的调试留给学生,但这是我很快为bash shell提出的,希望MAC足够接近:

function rounder
{
    local value=$1;
    local digits=${2:-3};

    local zeros="$( eval "printf '0%.0s' {1..$digits}" )"; #proper zeros
        # a bit of shell magic that repats the '0' $digits times.

    if (( value > 1$zeros )); then
        # large enough to require rounding
        local length=${#value};
        local digits_1=$(( $digits + 1 ));      #digits + 1
        local tval="${value:0:$digits_1}"; #leading digits, plus one
        tval=$(( $tval + 5 ));          #half-add
        local tlength=${#tval};         #check if carried a digit
        local zerox="";
        if (( tlength > length )); then
            zerox="0";
        fi
        value="${tval:0:$digits}${zeros:0:$((length-$digits))}$zerox";
    fi  

    echo "$value";
}

了解如何做得更短,但这是学生的另一项练习。

由于inherit problems within而避免浮点数学。

不包括各种特殊情况,例如负数。