Get ceiling integer from number in linux (BASH)

后端 未结 13 1955
陌清茗
陌清茗 2020-12-01 04:54

How would I do something like:

ceiling(N/500)

N representing a number.

But in a linux Bash script

相关标签:
13条回答
  • 2020-12-01 05:30

    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
    
    0 讨论(0)
  • 2020-12-01 05:31

    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
    }
    
    0 讨论(0)
  • 2020-12-01 05:35

    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
    
    0 讨论(0)
  • 2020-12-01 05:36

    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.

    0 讨论(0)
  • 2020-12-01 05:37

    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

    0 讨论(0)
  • 2020-12-01 05:37

    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
    
    0 讨论(0)
提交回复
热议问题