🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.unix.shell
Article #4147

Re: ksh->bash and floating point arithmetic

#4147
From: Chris F.A. Johnson
Date: Mon, 08 Dec 2003 18:22
101 lines
3913 bytes
On Mon, 08 Dec 2003 at 14:25 GMT, Tristan Miller wrote:
> Greetings.
> 
> I have a set of KornShell (ksh93) scripts, some fairly large, which I
> wish to convert to GNU bash scripts for the following reasons:
> 
> a) the KornShell licence is too restrictive;
> b) there is too much inconsistency in the version of ksh provided by
> various Unix vendors;
> c) in my experience, bash tends to be easier to compile and install than
> ksh93; and
> d) if I'm going to convert ksh93 code into anything, converting it into
> bash will probably require the least number of changes.
> 
> The reason the scripts were written in ksh93 to begin with is its
> support for floating-point arithmetic.
> 
> Up until now I have been replacing the ksh93-specific arithmetic
> operators with calls to bash functions which invoke bc.  This seems to
> work as expected, but apart from rewriting everything in, say, Perl, is
> there a better or more efficient way of getting floating-point
> arithmetic?

    I find that awk is considerably faster than bc; this may be
    implementation dependent. I use this function:

calc() { awk "BEGIN {print $*}"; }

    Floating point arithmetic can be implemented as shell functions
    which do not call any external comands; for example, this
    multiplication function is faster than calling awk:

fpmul() {
    places=
    tot=1
    shift=0
    qm=
    neg=

    for fpn
    do
      case $fpn in
	  -*) [ "$neg" = '-' ] && neg= || neg='-'
	      fpn=${fpn#-}
	      ;;
      esac
      case $fpn in
          .*) int=
	      dec=${fpn#?}
	      tot=$(( $tot * $dec ))
	      places=$places$dec
	      ;;

	  *.*) dec=${fpn#*.}
	       int=${fpn%.*}
	       places=$places$dec
	       tot=$(( $tot * $int$dec ))
	       ;;
	  *) tot=$(( $tot * $fpn ));;
      esac
    done

    while [ ${#qm} -lt ${#places} ]
    do
      qm=$qm'?'
    done

    while [ ${#qm} -gt ${#tot} ]
    do
      tot=0$tot
    done
    int=${tot%$qm}
    dec=${tot#$int}
    _FPMUL=$neg$int${dec:+.$dec}
    [ ${SILENT_FUNCS:-0} = 1 ] || echo "${_FPMUL}"
}

    Note that in bash, as in most shells, using command substitution
    to return a value is slow since it forks a new process (ksh93 is
    an exception).

    By setting a variable inside the function and referencing it in
    the calling code, a new process is avoided.

    This:

SILENT_FUNCS=1 fpmul 3.14159265 12.352
product=$_FPMUL

    is considerably faster than:

product=`fpmul 3.14159265 12.352`

    I don't know whether shell functions would be faster than awk when
    it comes to parsing mixed calculations (e.g. "3.456 * (4 + 1.414)").

-- 
    Chris F.A. Johnson                        http://cfaj.freeshell.org
    ===================================================================
    My code (if any) in this post is copyright 2003, Chris F.A. Johnson
    and may be copied under the terms of the GNU General Public License
Technical Details
Message-ID: <br2fgh$28dbor$1@ID-210011.news.uni-berlin.de>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!uni-berlin.de!cpe0030ab04dde2-cm023459906638.cpe.net.cable.rogers.COM!not-for-mail
References: <2726696.9viUAlbAWN@ID-187157.news.dfncis.de>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 109f73,c9a9cf8582f4663a
X-Google-Attributes: gid109f73,public
X-Google-Thread: 1012a6,c9a9cf8582f4663a
X-Google-Attributes: gid1012a6,public
X-Google-ArrivalTime: 2003-12-08 10:22:11 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!uni-berlin.de!cpe0030ab04dde2-cm023459906638.cpe.net.cable.rogers.COM!not-for-mail
From: "Chris F.A. Johnson" <c.fa.johnson@rogers.com>
Newsgroups: comp.unix.shell,gnu.utils.help
Subject: Re: ksh->bash and floating point arithmetic
Date: 8 Dec 2003 18:22:10 GMT
Lines: 101
Message-ID: <br2fgh$28dbor$1@ID-210011.news.uni-berlin.de>
References: <2726696.9viUAlbAWN@ID-187157.news.dfncis.de>
NNTP-Posting-Host: cpe0030ab04dde2-cm023459906638.cpe.net.cable.rogers.com (24.156.50.72)
X-Trace: news.uni-berlin.de 1070907730 75935515 24.156.50.72 ([210011])
User-Agent: slrn/0.9.7.4 (Linux)