help-bash
[Top][All Lists]
Advanced

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

Re: Kludge for handling REPL arithmetic expressions


From: Chris Elvidge
Subject: Re: Kludge for handling REPL arithmetic expressions
Date: Wed, 4 Aug 2021 14:49:09 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 Lightning/5.4

On 04/08/2021 12:39 pm, Greg Wooledge wrote:
On Wed, Aug 04, 2021 at 11:12:01AM +0100, Chris Elvidge wrote:
I was intrigued by this. So tried:
=() { echo "scale=5; $@" | bc; }

I'd suggest $* here.  You don't really want to preserve separate
arguments in this case.

Also, you really want bc -l, which also means you really don't want
to reduce the scale to merely 5.  (If you want to reduce the
percision of the answer, capture it with a command substitution, and
then feed it to printf for rounding.  Reducing the scale within bc
leads to extremely wrong answers in some cases.)

Seems to work for simple calculations.

A couple of questions, though.
1) How do you 'export -f ='? Or is it impossible?

Probably impossible, as it is an invalid shell "identifier".

2) How do you type in '= log(2048,2)' without getting a syntax error?

With quotes.  Also, "log()" is spelled "l()" in bc.

unicorn:~$ =() { echo "$*" | bc -l; }
unicorn:~$ = 'l(2048.2)'
7.62471663764133723968

Or with rounding:

unicorn:~$ =() { local n; n=$(echo "$*" | bc -l) || return; printf '%.5f\n' 
"$n"; }
unicorn:~$ = 'l(2048.2)'
7.62472

This is a cute little experiment, but it's not a path I'd choose for
myself.  What I do instead is keep a dedicated terminal window open
in a specific spot on my screen, with bc -l running interactively.
If I need to calculate something, I just focus on that window and type
my expressions there.

Also, I guess checking bc's exit status is pointless...

unicorn:~$ = 1/0
Runtime error (func=(main), adr=3): Divide by zero
0.00000
unicorn:~$ echo '1/0' | bc -l
Runtime error (func=(main), adr=3): Divide by zero
unicorn:~$ echo $?
0

*sigh*



Thanks Greg (and Eric for the idea and leading me to rediscover Euclid's Algorithm).

I've reduced it to:
=() { bc -l <<<"$*"; }

and (using d for /)

command_not_found_handle ()
{
    if [[ "$1" != =* ]]; then
        printf "%s: command not found\n" "$1" 1>&2;
        return 127;
    fi;
    set -- ${*/d/\/};
    set -- ${*#=};
    printf '%.3f\n' $(bc -l <<<"$*")
}


--
Chris Elvidge
England




reply via email to

[Prev in Thread] Current Thread [Next in Thread]