我应该如何做类似这样的事情:
ceiling(N/500)
N代表一个数字。
但在Linux的Bash脚本中
为什么使用外部脚本语言?默认情况下,您会得到地板(floor)。要得到天花板(ceil),请执行以下操作:
$ divide=8; by=3; (( result=(divide+by-1)/by )); echo $result
3
$ divide=9; by=3; (( result=(divide+by-1)/by )); echo $result
3
$ divide=10; by=3; (( result=(divide+by-1)/by )); echo $result
4
$ divide=11; by=3; (( result=(divide+by-1)/by )); echo $result
4
$ divide=12; by=3; (( result=(divide+by-1)/by )); echo $result
4
$ divide=13; by=3; (( result=(divide+by-1)/by )); echo $result
5
....
要考虑负数,你可以稍微增加些内容。可能有更干净的方法,但作为入门
$ divide=-10; by=10; neg=; if [ $divide -lt 0 ]; then (( divide=-divide )); neg=1; fi; (( result=(divide+by-1)/by )); if [ $neg ]; then (( result=-result )); fi; echo $result
-1
$ divide=10; by=10; neg=; if [ $divide -lt 0 ]; then (( divide=-divide )); neg=1; fi; (( result=(divide+by-1)/by )); if [ $neg ]; then (( result=-result )); fi; echo $result
1
(编辑将let ...
切换为(( ... ))
。)
echo $(((-10+10-1)/10))
的结果为零,而不是负一。 - Hubert Kariobash
仅支持固定大小的整数; $divide + $by - 1
可能会导致溢出。 - chepner使用天花板函数调用脚本语言。 给出$NUMBER
:
python -c "from math import ceil; print ceil($NUMBER/500.0)"
或者perl -w -e "use POSIX; print ceil($NUMBER/500.0), qq{\n}"
ceil($ARGV[0]/$ARGV[1])
来使用两个脚本参数吗?然后您将在脚本周围使用单引号。或者,使用双引号,您可以让shell替换其$1、$2。 - Jonathan Leffler以下是使用 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
}
ceiling_result=$((($1+$2-1)/$2))
- Jonathan Leffler#!/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
如果可以选择,您可以使用更好的 shell,例如支持浮点运算的 Zsh。
integer ceiling_result
ceiling_divide() {
ceiling_result=$(($1/$2))
echo $((ceiling_result+1))
}
ceiling_divide 1.234 500
$1/$2
可能是精确的。 - Michaël在数学上,天花板函数可以用地板函数来定义,即 ceiling(x) = -floor(-x)。而且,在将正浮点数转换为整数时,默认使用地板函数。
if [ $N -gt 0 ]; then expr 1 - $(expr $(expr 1 - $N) / 500); else expr $N / 500; fi
$ echo 10.001 | jq '.|ceil'
11
$ jq -n '-10.001 | ceil'
-10
在 Kalle 的优秀回答 上进行进一步说明,下面是一个将算法封装成函数的漂亮示例:
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
}
这里使用了一种针对负数的“伪”向上取整方法,即向最高的绝对值整数,例如 -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
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}
bash
可以使用printf
函数实现向上取整,例如:$ printf %.4f 0.12345
0.1235
但是如果你需要使用小数进行一些数学运算,你可以使用默认精度为20位小数的bc -l
,然后使用printf
将结果四舍五入。
printf %.3f $(echo '(5+50*3/20 + (19*2)/7 )' | bc -l)
17.929
printf
四舍五入到最近的整数,如果没有 +/-0.5
的小把戏,这个答案是错误的。 - Irfy如果除法返回一个非浮点数,此函数将不会加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
$((...))
的答案,在操作数已经是浮点数时会失败。例如,echo $((1.1))
会产生如下结果:-bash: 1.1: 语法错误:无效的算术运算符(错误标记为“.1”)
,甚至在尝试除法之前就会出错。 - Irfy