Jason Stelzer on 17 Sep 2009 07:33:07 -0700

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PLUG] floor/ceil in bash?

Thanks, again, that's why I asked.

There's no real user input involved, just properties files that are
created and reviewed before they're executed. The use of bc is
something I really should have thought of myself. Thanks for pointing
me in a much more technically correct direction.

On Thu, Sep 17, 2009 at 1:47 AM, Paul L. Snyder <plsnyder@drexel.edu> wrote:
> On September 16, 2009, "Jason Stelzer" <jason.stelzer@gmail.com>  wrote:
>> Well, to be fair....
>> First, thanks, that's a good idea. I'll just do that.
>> Second, I really just need to always round up the the nearest whole number.
> Just?
> I took another look at your code snippet.  It will indeed give you the
> ceiling of "something", as long as that something is the result of
> dividing two positive (or two negative) integer numbers.  This may be
> sufficient for your purposes.  You could avoid using the _MY_CEIL
> construct you dislike by employing command substitution as used in my
> previous suggestion, at the price of spawning a subshell.
> It's worth noting that bash is not giving you the floor as the result of
> arithmetic operations, it is giving you the result of integer division.
> This is the same as the floor only if both numbers are either positive
> or negative.  If one of the numbers is negative, the result of
> $(( -5 / 3 )) will be -1, not -2.
> If you want to do some math in bc rather than (as I originally
> assumed) just give it a floating-point number, you can make it
> safe for division with a small tweak.  As it stands, if do something
> like
>  $ MAX=5; DIVISOR=3
>  $ ceil("$MAX / $DIVISOR")
>  1
> bc will do the math but you'll get the wrong answer.  bc's scale
> defaults to 0, so an integer is returned by the division operation
> and the ceiling of an integer is itself.  Change ceil to
>  function newceil () { echo "define ceil (x) {if (x<0) {return x/1} \
>    else {if (scale(x)==0) {return x} else {return x/1 + 1 }}} ; \
>    scale=-1; y=$1; scale=0; ceil(y)" | bc; }
> and you can give it a tasty arithmetic expression:
>  $ MAX=5; DIVISOR=3
>  $ newceil("$MAX / $DIVISOR")
>  2
> Quotes are necessary to make it all one argument; you might be able to
> get around this by using $* instead of $1 in the function, but I haven't
> tested that, so be careful.  Even as it stands there may be weird edge
> cases I haven't thought about.
> Don't trust something like this with user input that hasn't been
> sanitized, but that's good practice for shell scripts in general.
> Paul
> ___________________________________________________________________________
> Philadelphia Linux Users Group         --        http://www.phillylinux.org
> Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
> General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug

Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug