5

The context is there are 2 variables that get divided to a floating point result like so:

printf "%0.5f\n" $(echo 305/15 | bc -l)
20.33333

How can I always round up to the next integer i.e. 21? This is not about rounding up a value above 20.5 to 21 i.e. nearest integer. I'm asking because I want a value to be either exactly the integer or the next integer if it's above in whatever way. So how can I evaluate that? With an if statement? If I put a float there the shell complains it expects an integer. I don't fully understand how to leverage the information in a Q&A such as this one to effect a conversion "upward" to the next integer. Something I'm missing?

1

7 Answers 7

8

You can use bc features for that:

echo "a=305; b=15; if ( a%b ) a/b+1 else a/b" | bc
1
  • Thank you, that fit in perfectly and helped me quite a lot!
    – user44370
    Nov 17, 2014 at 21:40
4

Try:

ceil() {                                                                       
  echo "define ceil (x) {if (x<0) {return x/1} \
        else {if (scale(x)==0) {return x} \
        else {return x/1 + 1 }}} ; ceil($1)" | bc
}

Then:

$ ceil 5.1
6
$ ceil 5.5
6
$ ceil 5.9
6
2
  • Thank you! I like to have such functions handy. I tried it!
    – user44370
    Nov 17, 2014 at 21:40
  • 1
    as noted by @Jane, that gives 6 for ceil 5.0. Aug 10, 2017 at 10:33
4

for positive integers:

a=305
b=15
echo $((a%b?a/b+1:a/b))
21
1

In ksh93 or zsh, you can use the ceil() function in arithmetic expressions.

In zsh, you need to load the zsh/mathfunc module first (zmodload zsh/mathfunc)

In both ksh93 and zsh, note that for a division to yield a float, you need at least one operands to be a float (otherwise you get an integer division, like in C), so:

echo "$((ceil(305. / 15)))"

Otherwise $((ceil(305 / 15))) would be $((ceil(20))). In ksh93, you'll need to change that to $((ceil(305, / 15))) if the user's locale indicates that the decimal separator is a comma.

The above outputs 21 in ksh93, and 21. (to make sure it's still a float) in zsh. If you want to avoid that trailing ., you can convert to integer with:

echo $(( int(ceil(305. / 15)) ))
1

Through awk and add 0.5 to the result then .f will round it up to nearest number by itself.

awk 'BEGIN{printf("%.f\n", (305/15)+0.5)}' 
21

If you want its floor function, use -0.5 instead

0

Supplement to the answer of cuonglm.

If it shall round negative values down and positive values up, one can define in addition to ceil() as above:

ceil2() {                                              
        echo "define ceil2 (x) {if (x/1 == x) {return x} \
        else { if (x<0) {return x/1 -1} \
        else {return x/1 + 1 }}} ; ceil2($1)" | bc
}

Edit: I changed if (scale(x)==0) to if (x/1 == x) ; otherwise 6.0 will be rounded up to 7

0

You can use the awk Velour library:

$ velour -n 'print mt_ceil(305 / 15)'
21

You must log in to answer this question.