web-dev-qa-db-ja.com

Linuxの数値から天井整数を取得(BASH)

どのように私は次のようなことをしますか:

ceiling(N/500)

Nは数値を表します。

しかし、Linux Bashスクリプトでは

37
Mint

Ceil関数を使用してスクリプト言語を呼び出します。与えられた$NUMBER

python -c "from math import ceil; print ceil($NUMBER/500.0)"

または

Perl -w -e "use POSIX; print ceil($NUMBER/500.0), qq{\n}"
16
Josh McFadden

外部スクリプト言語を使用する理由デフォルトでフロアを取得します。天井を取得するには、

$ divide=8; by=3; let result=($divide+$by-1)/$by; echo $result
3
$ divide=9; by=3; let result=($divide+$by-1)/$by; echo $result
3
$ divide=10; by=3; let result=($divide+$by-1)/$by; echo $result
4
$ divide=11; by=3; let result=($divide+$by-1)/$by; echo $result
4
$ divide=12; by=3; let result=($divide+$by-1)/$by; echo $result
4
$ divide=13; by=3; let result=($divide+$by-1)/$by; echo $result
5
....

負の数を考慮するには、少し強化することができます。おそらくそこにあるが、初心者向けのよりクリーンな方法

$ divide=-10; by=10; neg=; if [ $divide -lt 0 ]; then let divide=-$divide; neg=1; fi; let result=($divide+$by-1)/$by; if [ $neg ]; then let result=-$result; fi; echo $result
-1

$ divide=10; by=10; neg=; if [ $divide -lt 0 ]; then let divide=-$divide; neg=1; fi; let result=($divide+$by-1)/$by; if [ $neg ]; then let result=-$result; fi; echo $result
1
75
Kalle

Bcを使用したソリューションです(ほぼすべての場所にインストールする必要があります)。

ceiling_divide() {
  ceiling_result=`echo "($1 + $2 - 1)/$2" | bc`
}

純粋にbashの別の例を次に示します。

# Call it with two numbers.
# It has no error checking.
# It places the result in a global since return() will sometimes truncate at 255.

# Short form from comments (thanks: Jonathan Leffler)
ceiling_divide() {
  ceiling_result=$((($1+$2-1)/$2))
}

# Long drawn out form.
ceiling_divide() {
  # Normal integer divide.
  ceiling_result=$(($1/$2))
  # If there is any remainder...
  if [ $(($1%$2)) -gt 0 ]; then
    # rount up to the next integer
    ceiling_result=$((ceiling_result + 1))
  fi
  # debugging
  # echo $ceiling_result
}
6
Harvey

Awkを使用できます

#!/bin/bash
number="$1"
divisor="$2"
ceiling() {
  awk -vnumber="$number" -vdiv="$divisor" '
  function ceiling(x){return x%1 ? int(x)+1 : x}
  BEGIN{ print ceiling(number/div) }'
}
ceiling

出力

$ ./Shell.sh 1.234 500
1

または、選択肢がある場合は、Zshなどの浮動小数点を実行するより良いシェルを使用できます

integer ceiling_result
ceiling_divide() {
  ceiling_result=$(($1/$2))
  echo $((ceiling_result+1))
}

ceiling_divide 1.234 500
5
ghostdog74

数学的には、天井の関数はfloor、ceiling(x)= -floor(-x)で定義できます。また、floatを整数に変換するときのデフォルトはfloorです。

if [ $N -gt 0 ]; then expr 1 - $(expr $(expr 1 - $N) / 500); else expr $N / 500; fi

参照 https://en.wikipedia.org/wiki/Floor_and_ceiling_functions

4
Frank R.

Kalle's great answer を少し拡張して、関数にうまく詰め込まれたアルゴリズムを以下に示します。

_ceildiv() {
    local num=$1
    local div=$2
    echo $(( (num + div - 1) / div ))
}
_

またはワンライナーとして:

_ceildiv(){ echo $((($1+$2-1)/$2)); }
_

派手になりたい場合は、より堅牢なバージョン検証入力を使用して、入力が数値であるかどうかを確認し、負の数も処理できます。

_ceildiv() {
    local num=${1:-0}
    local div=${2:-1}
    if ! ((div)); then
        return 1
    fi
    if ((num >= 0)); then
        echo $(( (num + div - 1) / div ))
    else
        echo $(( -(-num + div - 1) / div ))
    fi
}
_

これは、負の数に「偽の」セルを使用して、最高absolute整数、つまり-10ではなく-3 = -4であり、-3ではありません。 -3> -4として。 「真の」セルが必要な場合は、elseの代わりに$(( num / div ))を使用してください

そして、それを次のように使用します:

 $ ceildiv 10 3 
 4 
 $ ceildiv 501 500 
 2 
 $ ceildiv 0 3 
 0 
 $ ceildiv -10 1 
-10 
 $ ceildiv -10 3 
-4 
2
MestreLion
Floor () {
  DIVIDEND=${1}
  DIVISOR=${2}
  RESULT=$(( ( ${DIVIDEND} - ( ${DIVIDEND} % ${DIVISOR}) )/${DIVISOR} ))
  echo ${RESULT}
}
R=$( Floor 8 3 )
echo ${R}
Ceiling () {
  DIVIDEND=${1}
  DIVISOR=${2}
  $(( ( ( ${DIVIDEND} - ( ${DIVIDEND} % ${DIVISOR}) )/${DIVISOR} ) + 1 ))
  echo ${RESULT}
}
R=$( Ceiling 8 3 )
echo ${R}
2
bsaldivar

豪華な 'printf'を使用すると 1 は次の整数に切り上げられます

printf %.0f $float
or
printf %.0f `your calculation formula`
or
printf %.0f $(your calculation formula)

ref: 変数から小数点を削除する方法?

1
splaisan

これは、Awkを使用した簡単なソリューションです。

($ a/$ b)の上限を使用する場合

echo "$a $b" | awk '{print int( ($1/$2) + 1 )}'

そして床の使用

echo "$a $b" | awk '{print int($1/$2)}'

Awkの行の最初のフィールドとして被除数「$ a」をエコーし​​、2番目として除数「$ b」をエコーすることに注意してください。

0

除算が浮動小数点数を返さない場合、この関数は1を追加しません。

function ceiling {
    DIVIDEND=${1}
    DIVISOR=${2}
    if [ $(( DIVIDEND % DIVISOR )) -gt 0 ]; then
            RESULT=$(( ( ( $DIVIDEND - ( $DIVIDEND % $DIVISOR ) ) / $DIVISOR ) + 1 ))
    else
            RESULT=$(( $DIVIDEND / $DIVISOR ))
    fi
    echo $RESULT
}

次のように使用します。

echo $( ceiling 100 33 )
> 4
0
Regaddi

関数を指定せずに、次のawkスクリプトを使用できます。

echo x y | awk '{ r=$1 % $2; q=$1/y; if (r != 0) q=int(q+1); print q}'

これに論理エラーが発生するかどうかはわかりません。正してください。

0
Kemin Zhou

より簡潔なAwkロジック

awk '
function ceil(ip) {
  print ip%1 ? int(ip)+1 : ip
}  
BEGIN {
  ceil(1000/500)
  ceil(1001/500)
}
'

結果

 2 
 3 
0
Steven Penny