2016-04-17 8 views
1

Mac端末では、大きな数字を丸めたいと思います。例えばシェルコマンドで大きな数値を丸める方法は?

、10時

^13位:
1234567812345678 - > 1230000000000000

または10^12位で:
1234567812345678 - > 1235000000000000

だから私は希望場所を指定し、丸められた番号を取得します。 どうすればいいですか?

+0

これは、丸めよりも切り捨てに似ており、正規表現を使用して文字の置換を行うことができます。 – mpez0

答えて

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を数え、1文字を取ります。 -$2の前にスペースがなければなりません(またはカッコ内にある必要があります)。それ以外の場合は、別の拡張として解釈され、$1が設定されていないか、nullであるかどうかがチェックされます。

+1

うまくやった。私が思いついたよりもはるかにエレガントなので、私の純粋な 'bash'ソリューションをあなたのものと置き換えました。 – mklement0

+0

私は欲しかったものを正確に得ました。どうもありがとうございました。 – Isaac

0

実際には、n桁の有効数字に丸めたい場合は、伝統的な数学と文字列を混ぜることで最も効果的です。

深刻なデバッグが学生に任されているが、これは、私はすぐにbashシェルのために思い付いたものですし、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による浮動小数点数の回避。

マイナスの数字のようなあらゆる特殊なケースはカバーされません。

+0

'zeros =" $(eval "printf ...')の代わりに、 'printf -v zero 'を使って同じ効果を得ることができます。 –

1

awk[s]printf機能は、倍精度浮動小数点演算の範囲内で、あなたのため丸め行うことができます。純粋なbash実装については

$ 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を参照してください。

関連する問題