How would I do something like:
ceiling(N/500)
N representing a number.
But in a linux Bash script
Expanding a bit on Kalle's great answer, here's the algorithm nicely packed in a function:
ceildiv() {
local num=$1
local div=$2
echo $(( (num + div - 1) / div ))
}
or as a one-liner:
ceildiv(){ echo $((($1+$2-1)/$2)); }
If you want to get fancy, you could use a more robust version validates input to check if they're numerical, also handles negative numbers:
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
}
This uses a "fake" ceil for negative numbers, to the highest absolute integer, ie, -10 / 3 = -4 and not -3 as it should, as -3 > -4. If you want a "true" ceil, use $(( num / div ))
instead after the else
And then use it like:
$ ceildiv 10 3 4 $ ceildiv 501 500 2 $ ceildiv 0 3 0 $ ceildiv -10 1 -10 $ ceildiv -10 3 -4
Here's a solution using bc (which should be installed just about everywhere):
ceiling_divide() {
ceiling_result=`echo "($1 + $2 - 1)/$2" | bc`
}
Here's another purely in 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
}
You can use 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
output
$ ./shell.sh 1.234 500
1
Or if there's a choice, you can use a better shell that does floating point, eg Zsh
integer ceiling_result
ceiling_divide() {
ceiling_result=$(($1/$2))
echo $((ceiling_result+1))
}
ceiling_divide 1.234 500
This is a simple solution using Awk:
If you want the ceil of ($a/$b) use
echo "$a $b" | awk '{print int( ($1/$2) + 1 )}'
and the floor use
echo "$a $b" | awk '{print int($1/$2)}'
Note that I just echo the dividend '$a' as the first field of the line to awk and the divisor '$b' as the second.
Mathematically, the function of ceiling can be define with floor, ceiling(x) = -floor(-x). And, floor is the default when converting a positive float to integer.
if [ $N -gt 0 ]; then expr 1 - $(expr $(expr 1 - $N) / 500); else expr $N / 500; fi
Ref. https://en.wikipedia.org/wiki/Floor_and_ceiling_functions
This function wont't add 1, if the division returns a non-floating number.
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
}
Use it like this:
echo $( ceiling 100 33 )
> 4