从Linux中的数字获取上限整数(BASH)

发布于 2024-08-24 07:25:41 字数 99 浏览 9 评论 0 原文

我会怎么做:

ceiling(N/500)

N 代表一个数字。

但在 Linux Bash 脚本中

How would I do something like:

ceiling(N/500)

N representing a number.

But in a linux Bash script

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

失去的东西太少 2024-08-31 07:25:41

为什么要使用外部脚本语言?默认情况下您获得发言权。要获得 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 ... 切换为 (( ... ))。)

Why use external script languages? You get floor by default. To get ceil, do

$ 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
....

To take negative numbers into account you can beef it up a bit. Probably cleaner ways out there but for starters

$ 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

(Edited to switch let ... to (( ... )).)

苍暮颜 2024-08-31 07:25:41

使用 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}"

Call out to a scripting language with a ceil function. Given $NUMBER:

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

or

perl -w -e "use POSIX; print ceil($NUMBER/500.0), qq{\n}"
丿*梦醉红颜 2024-08-31 07:25:41

这是一个使用 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
}

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
}
鹤舞 2024-08-31 07:25:41

您可以使用 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

或者如果有选择,您可以使用更好的 shell
浮点数,例如 Zsh

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

ceiling_divide 1.234 500

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
生死何惧 2024-08-31 07:25:41

稍微扩展一下 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
}

这对负数使用“假”ceil,直到最高的绝对整数,即-10 / 3 = -4,而不是应有的-3,因为-3 > -4。如果您想要一个“true”ceil,请在 else 之后使用 $(( num / div ))

,然后使用它,如下所示:

$ ceildiv 10 3
4
$ ceildiv 501 500
2
$ ceildiv 0 3
0
$ ceildiv -10 1
-10
$ ceildiv -10 3
-4

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
柠栀 2024-08-31 07:25:41

从数学上讲,天花板的函数可以用地板来定义,天花板(x)= -地板(-x)。并且,将正浮点数转换为整数时,下限是默认值。

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

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

爱的故事 2024-08-31 07:25:41

如果已安装,则可以使用 jq 。它是“sed for JSON”,但我发现它对于像这样的简单任务也非常方便。

示例:

$ echo 10.001 | jq '.|ceil'
11

$ jq -n '-10.001 | ceil'
-10

You can use jq if you have it installed. It's "sed for JSON", but I find it surprisingly handy for simple tasks like this too.

Examples:

$ echo 10.001 | jq '.|ceil'
11

$ jq -n '-10.001 | ceil'
-10
睡美人的小仙女 2024-08-31 07:25:41
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}
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}
贩梦商人 2024-08-31 07:25:41

如果您有十进制数字的字符串表示形式,则 bash 确实支持使用 printf 函数进行上限,如下所示:

$ printf %.4f 0.12345
0.1235

但是如果您需要使用小数进行一些数学运算,则可以使用 < code>bc -l 默认情况下缩放至 20 位小数,然后将结果与 printf 一起使用以进行四舍五入。

printf %.3f $(echo '(5+50*3/20 + (19*2)/7 )' | bc -l)
17.929

If you have a string representation of a decimal number, bash does support ceiling using printf function like this:

$ printf %.4f 0.12345
0.1235

But if you need to do some math using decimals, you can use bc -l that by default scales to 20 decimals, then use the result with printf to round it.

printf %.3f $(echo '(5+50*3/20 + (19*2)/7 )' | bc -l)
17.929
倥絔 2024-08-31 07:25:41

这是使用 awk 的一个简单解决方案:

如果您想要使用 ($a/$b) 的 ceil

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

和使用下限

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

请注意,我只是将被除数 '$a' 作为 awk 行的第一个字段和除数 ' $b' 作为第二个。

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.

凉栀 2024-08-31 07:25:41

一些更简洁的 awk 逻辑

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

结果

2
3

Some more concise Awk logic

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

Result

2
3
秋凉 2024-08-31 07:25:41

如果除法返回非浮点数,则该函数不会加 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

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
素衣风尘叹 2024-08-31 07:25:41

一些更简洁的 awk 逻辑

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

结果

2
3

Some more concise Awk logic

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

Result

2
3
韵柒 2024-08-31 07:25:41

使用华丽的 'printf' 1 将四舍五入到下一个整数

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

ref: 如何从变量中删除小数?

Using the gorgeous 'printf' 1 will round up to the next integer

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

ref: how to remove decimal from a variable?

黑凤梨 2024-08-31 07:25:41

在不指定任何函数的情况下,我们可以使用以下 awk 脚本:

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

不确定这个脚本是否会出现任何逻辑错误。请纠正。

Without specifying any function, we can use the following awk script:

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

Not sure this one get any logical error or not. Please correct.

恰似旧人归 2024-08-31 07:25:41

如果您已经熟悉 Python 库,那么您可能想要定义这个 bash 函数,而不是学习 bc :

pc () { pyexpr="from math import *; print($@)"; python -c "$pyexpr"; }

那么:

pc "ceil(3/4)"
1

但任何有效的 python 表达式 都可以工作:

pc pi / 4
0.7853981633974483

pc "'\n'.join(['Pythagoras said that %3.2f^2 + %3.2f^2 is always %3.2f'
    % (sin(ai), cos(ai), sin(ai)**2 + cos(ai)**2)
    for ai in [pi / 4 * k for k in range(8)]])"
Pythagoras said that 0.00^2 + 1.00^2 is always 1.00
Pythagoras said that 0.71^2 + 0.71^2 is always 1.00
Pythagoras said that 1.00^2 + 0.00^2 is always 1.00
Pythagoras said that 0.71^2 + -0.71^2 is always 1.00
Pythagoras said that 0.00^2 + -1.00^2 is always 1.00
Pythagoras said that -0.71^2 + -0.71^2 is always 1.00
Pythagoras said that -1.00^2 + -0.00^2 is always 1.00
Pythagoras said that -0.71^2 + 0.71^2 is always 1.00

If you are already familiar with the Python library, then rather than learn bc, you might want to define this bash function:

pc () { pyexpr="from math import *; print($@)"; python -c "$pyexpr"; }

Then:

pc "ceil(3/4)"
1

but also any valid python expression works:

pc pi / 4
0.7853981633974483

pc "'\n'.join(['Pythagoras said that %3.2f^2 + %3.2f^2 is always %3.2f'
    % (sin(ai), cos(ai), sin(ai)**2 + cos(ai)**2)
    for ai in [pi / 4 * k for k in range(8)]])"
Pythagoras said that 0.00^2 + 1.00^2 is always 1.00
Pythagoras said that 0.71^2 + 0.71^2 is always 1.00
Pythagoras said that 1.00^2 + 0.00^2 is always 1.00
Pythagoras said that 0.71^2 + -0.71^2 is always 1.00
Pythagoras said that 0.00^2 + -1.00^2 is always 1.00
Pythagoras said that -0.71^2 + -0.71^2 is always 1.00
Pythagoras said that -1.00^2 + -0.00^2 is always 1.00
Pythagoras said that -0.71^2 + 0.71^2 is always 1.00
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文