337

I am trying to divide two image widths in a Bash script, but bash gives me 0 as the result:

RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))

I did study the Bash guide and I know I should use bc, in all examples in internet they use bc. In echo I tried to put the same thing in my SCALE but it didn't work.

Here is the example I found in the tutorials:

echo "scale=2; ${userinput}" | bc 

How can I get Bash to give me a float like 0.5?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Medya Gh
  • 4,563
  • 5
  • 23
  • 35
  • 10
    A comment for everybody trying to do floating point arithmetic in your script, ask yourself: _do I really need floating point arithmetic?_ sometimes you can really get along without. See, for example the last part of [BashFAQ/022](http://mywiki.wooledge.org/BashFAQ/022). – gniourf_gniourf Feb 16 '15 at 14:44
  • 1
    [It is possible to teach bash e.g. integer division with floating point results.](http://stackoverflow.com/a/24431665/3776858) – Cyrus Apr 22 '17 at 08:47

24 Answers24

315

You can't. bash only does integers; you must delegate to a tool such as bc.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 14
    how can I delegate a tool like bc in to put the answer in RESULT variable? – Medya Gh Oct 04 '12 at 07:19
  • 2
    so you mean like VAR=$(echo "scale=2; $(($IMG_WIDTH/$IMG2_WIDTH))" | bc) ? – Medya Gh Oct 04 '12 at 07:22
  • 72
    @Shevin `VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)` or `VAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")` without $(( )) (double parentheses) ; which is expanded by the bash before executing command – Nahuel Fouilleul Oct 04 '12 at 07:32
  • @CMCDragonkai: awk is not bash. – Ignacio Vazquez-Abrams Jun 26 '14 at 06:48
  • 5
    True, but awk is generally more likely to be already installed in the system. – CMCDragonkai Jun 26 '14 at 06:57
  • 10
    @NahuelFouilleul You have the best answer here. Should really be its own answer, and accepted as the answer. This particular line was incredibly useful: VAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH") – David Oct 01 '14 at 03:28
  • 1
    Actually [you can](http://www.linuxjournal.com/content/floating-point-math-bash) but i would recommend using a dedicated tool (like `bc`, `dc`, ...). – bufh Jul 20 '15 at 09:48
  • that's such an interesting parallel to javascript that ONLY has doubles :O. That said, i wonder if anyone wrote a floating/double manipulation functions in pure bash yet. I know one non bash version could just be `($_ = eval join '', @ARGV) && print`. so that `./app 2/3` prints `0.666666666666667`. I'm kinda amazed that my bash supports `declare -i 0x1000000000000000` being `1152921504606846976`, i'd think it was 32 bits. – Dmytro Jul 15 '17 at 06:04
  • You can use bash functions - no need for another tool. So `must` is not correct. – bebbo Jan 31 '20 at 21:17
  • So how about an example of using bc to accomplish this? – Ken Ingram Jun 15 '21 at 07:53
  • This answer is partially wrong. bc explicitly does __not__ support floating numbers. It has scaled fixed-point numbers. See documentation on scale=# as well as the -l (lowercase L) option. – Katastic Voyage Oct 15 '21 at 10:10
279

you can do this:

bc <<< 'scale=2; 100/3'
33.33

UPDATE 20130926 : you can use:

bc -l <<< '100/3' # saves a few hits
33.33333333333333333333
famzah
  • 1,462
  • 18
  • 21
aayoubi
  • 11,285
  • 3
  • 22
  • 20
  • 17
    @AndreasSpindler Kind of an old post, but in case anyone would like to know, this can be changed by applying the scale command eg. `bc -l <<< 'scale=2; 100/3'` – Martie Sep 15 '15 at 08:42
  • Just watch out if you're hoping to get an integer for later use in bash by using scale=0. As of v1.06.95, bc, for some reason, ignores the scale variable when the input numbers have a decimal part. Maybe this is in the docs, but I couldn't find it. Try: echo $(bc -l <<< 'scale=0; 1*3.3333') – Greg Bell Nov 11 '16 at 01:15
  • 1
    @GregBell The man page says `Unless specifically mentioned the scale of the result is the maximum scale of the expressions involved.` And there is an extra note for `/` operator: `The scale of the result is the value of the variable scale.` – psmith Jan 16 '17 at 05:48
  • 2
    Thanks @psmith. Interestingly, for / it says "the scale of the result is the value of the variable scale" but not so for multiplication. My better examples: `bc <<< 'scale=1; 1*3.00001'` scale is really 5 for some reason, `bc <<< 'scale=1; 1/3.000001'` scale is 1. Interestingly, dividing by 1 sets it straight: `bc <<< 'scale=1; 1*3.00001/1'` scale is 1 – Greg Bell Jan 17 '17 at 20:55
  • Why 3 left angle brackets `<<<` for the `bc` command? I've never seen this before. What does `<<<` mean? When else is it used? UPDATE: I posted this as a question here: https://stackoverflow.com/questions/58478964/what-do-three-left-angle-brackets-mean-in-bash – Gabriel Staples Oct 21 '19 at 02:02
  • Now that I've learned `<<<` is a **here string**, I've decided I like the `echo` plus pipe approach better, as it allows me to do the calculation, store it into a bash variable, then use it later, as I demonstrate in my own answer here: https://stackoverflow.com/questions/12722095/how-do-i-use-floating-point-division-in-bash/58479867#58479867. – Gabriel Staples Oct 21 '19 at 04:41
  • 1
    To prevent ["Syntax error: redirection unexpected"](https://stackoverflow.com/q/2462317/9157799), use `echo 'scale=2; 100/3' | bc` instead of `bc <<< 'scale=2; 100/3'` – M Imam Pratama Jan 20 '22 at 11:02
213

bash

As noted by others, bash does not support floating point arithmetic, although you could fake it with some fixed decimal trickery, e.g. with two decimals:

echo $(( 100 * 1 / 3 )) | sed -e 's/..$/.&/;t' -e 's/.$/.0&/'

Output:

.33

See Nilfred's answer for a similar but more concise approach.

Alternatives

Besides the mentioned bc and awk alternatives there are also the following:

clisp

clisp -x '(/ 1.0 3)'

with cleaned up output:

clisp --quiet -x '(/ 1.0 3)'

or through stdin:

echo '(/ 1.0 3)' | clisp --quiet | tail -n1

dc

echo 2k 1 3 /p | dc

genius cli calculator

echo 1/3.0 | genius

ghostscript

echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p' 

gnuplot

echo 'pr 1/3.' | gnuplot

Imagemagick

convert xc: -format '%[fx:1/3]' info:

or through stdin:

echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }

jq

jq -n 1/3

or through stdin:

echo 1/3 | jq -nf /dev/stdin

ksh

echo 'print $(( 1/3. ))' | ksh

lua

lua -e 'print(1/3)'

or through stdin:

echo 'print(1/3)' | lua

maxima

echo '1/3,numer;' | maxima

with cleaned up output:

echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'

node

echo 1/3 | node -p

octave

echo 1/3 | octave

perl

echo print 1/3 | perl

python2

echo print 1/3. | python2

python3

echo 'print(1/3)' | python3

R

echo 1/3 | R --no-save

with cleaned up output:

echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'

ruby

echo puts 1/3.0 | ruby

units

units 1/3

with compact output:

units --com 1/3

wcalc

echo 1/3 | wcalc

with cleaned up output:

echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2

zsh

print $(( 1/3. ))

or through stdin:

echo 'print $(( 1/3. ))' | zsh

Other sources

Stéphane Chazelas answered a similar question over on UL.

Thor
  • 45,082
  • 11
  • 119
  • 130
  • 14
    Great answer. I know it was posted a few years after the question but is more deserving of being the accepted answer. – Brian Cline Dec 14 '16 at 19:04
  • 5
    If you have zsh available, then it's worth considering to write your script in zsh instead of Bash – Andrea Corbellini Apr 29 '18 at 02:09
  • Nice list. Especially `echo 1/3 | node -p` is short. – Johnny Wong Oct 09 '19 at 10:07
  • Nice list. Sadly, the very first `bash` approach has a flaw. If the result has less than two digits (= simulated decimal places) then `sed` won't do the replacement. Example for `1 / 50`: `echo $(( 100*1/50)) | sed 's/..$/.&/'` prints `2` instead of `0.02`. – Socowi Mar 28 '21 at 16:57
  • @Socowi: indeed, in that case a second substitution is needed, see updated version. – Thor Mar 29 '21 at 03:58
  • `puts` may be better for Ruby – berezovskyi Jun 24 '21 at 16:22
  • 3
    It should also be heavily stressed that bc DOES NOT support floating point numbers. It uses FIXED point numbers and that's a big distinction. – Katastic Voyage Oct 15 '21 at 10:11
  • I love answers like this thanks for putting together a list for every language! – Andrew Apr 04 '22 at 17:32
  • I think the alternatives are not practical answer a part of "dc" or "bc" all the examples are using a heavy interpreter to make a simple operation. – Emmanuel Oct 30 '22 at 08:04
45

Improving a little the answer of marvin:

RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")

bc doesn't come always as installed package.

adrianlzt
  • 1,862
  • 20
  • 11
  • 5
    The awk script needs an `exit` to prevent it from reading from its input stream. I also suggest using awk's `-v` flags to prevent leaning toothpick syndrome. So: `RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')` – aecolley Mar 14 '15 at 15:02
  • 3
    A more awkish way to do this would be to read the arguments from the input stream: `RESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "`. – jmster Jun 08 '15 at 18:13
  • 1
    `bc` is part of POSIX, it is usually preinstalled. – fuz Aug 24 '15 at 12:48
  • this worked for me using git bash in windows 7 ... thanks :) – The Beast Apr 16 '16 at 03:59
41

You could use bc by the -l option (the L letter)

RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
user1314742
  • 2,865
  • 3
  • 28
  • 34
34

As an alternative to bc, you can use awk within your script.

For example:

echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'

In the above, " %.2f " tells the printf function to return a floating point number with two digits after the decimal place. I used echo to pipe in the variables as fields since awk operates properly on them. " $1 " and " $2 " refer to the first and second fields input into awk.

And you can store the result as some other variable using:

RESULT = `echo ...`
marvin
  • 581
  • 5
  • 9
26

Well, before float was a time where fixed decimals logic was used:

IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33

Last line is a bashim, if not using bash, try this code instead:

IMG_WIDTH=100
IMG2_WIDTH=3
INTEGER=$(($IMG_WIDTH/$IMG2_WIDTH))
DECIMAL=$(tail -c 3 <<< $((${IMG_WIDTH}00/$IMG2_WIDTH)))
RESULT=$INTEGER.$DECIMAL
echo $RESULT
33.33

The rationale behind the code is: multiply by 100 before divide to get 2 decimals.

Nilfred
  • 361
  • 3
  • 3
  • 1
    the technical term is [Fixed-point arithmetic](https://en.wikipedia.org/wiki/Fixed-point_arithmetic) – milahu Oct 17 '22 at 07:21
  • To handle tiny results (e.g. `IMG2_WIDTH=3000`) and prevent an error, add this line before the echo (in bash): `[[ ${#RESULT} -lt 2 ]] && RESULT="0$RESULT"` – Bryan Roach Mar 14 '23 at 17:02
20

It's perfect time to try zsh, an (almost) bash superset, with many additional nice features including floating point math. Here is what your example would be like in zsh:

% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875

This post may help you: bash - Worth switching to zsh for casual use?

Community
  • 1
  • 1
Penghe Geng
  • 13,286
  • 5
  • 31
  • 40
  • 4
    I'm a huge fan of zsh and have been using it for the last 4 years, but interactive use is a good emphasis here. A script that requires zsh is usually not going to be very portable across a diverse set of machines as it's usually not standard, sadly (to be fair, maybe that's okay; OP didn't say quite how it'll be used). – Brian Cline Dec 14 '16 at 19:10
6

If you found the variant of your preference you can also wrap it into a function.

Here I'm wrapping some bashism into a div function:

One liner:

function div { local _d=${3:-2}; local _n=0000000000; _n=${_n:0:$_d}; local _r=$(($1$_n/$2)); _r=${_r:0:-$_d}.${_r: -$_d}; echo $_r;}

Or multi line:

function div {
  local _d=${3:-2}
  local _n=0000000000
  _n=${_n:0:$_d}
  local _r=$(($1$_n/$2))
  _r=${_r:0:-$_d}.${_r: -$_d}
  echo $_r
}

Now you have the function

div <dividend> <divisor> [<precision=2>]

and use it like

> div 1 2
.50

> div 273 123 5
2.21951

> x=$(div 22 7)
> echo $x
3.14

UPDATE I added a little script which provides you the basic operations with floating point numbers for bash:

Usage:

> add 1.2 3.45
4.65
> sub 1000 .007
999.993
> mul 1.1 7.07
7.7770
> div 10 3
3.
> div 10 3.000
3.333

And here the script:

#!/bin/bash
__op() {
        local z=00000000000000000000000000000000
        local a1=${1%.*}
        local x1=${1//./}
        local n1=$((${#x1}-${#a1}))
        local a2=${2%.*}
        local x2=${2//./}
        local n2=$((${#x2}-${#a2}))
        local n=$n1
        if (($n1 < $n2)); then
                local n=$n2
                x1=$x1${z:0:$(($n2-$n1))}
        fi
        if (($n1 > $n2)); then
                x2=$x2${z:0:$(($n1-$n2))}
        fi
        if [ "$3" == "/" ]; then
                x1=$x1${z:0:$n}
        fi
        local r=$(($x1"$3"$x2))
        local l=$((${#r}-$n))
        if [ "$3" == "*" ]; then
                l=$(($l-$n))
        fi
        echo ${r:0:$l}.${r:$l}
}
add() { __op $1 $2 + ;}
sub() { __op $1 $2 - ;}
mul() { __op $1 $2 "*" ;}
div() { __op $1 $2 / ;}
bebbo
  • 2,830
  • 1
  • 32
  • 37
6
  1. How to do floating point calculations in bash:

    Instead of using "here strings" (<<<) with the bc command, like one of the most-upvoted examples does, here's my favorite bc floating point example, right from the EXAMPLES section of the bc man pages (see man bc for the manual pages).

    Before we begin, know that an equation for pi is: pi = 4*atan(1). a() below is the bc math function for atan().

    1. This is how to store the result of a floating point calculation into a bash variable--in this case into a variable called pi. Note that scale=10 sets the number of decimal digits of precision to 10 in this case. Any decimal digits after this place are truncated.

      pi=$(echo "scale=10; 4*a(1)" | bc -l)
      
    2. Now, to have a single line of code that also prints out the value of this variable, simply add the echo command to the end as a follow-up command, as follows. Note the truncation at 10 decimal places, as commanded:

      pi=$(echo "scale=10; 4*a(1)" | bc -l); echo $pi
      3.1415926532
      
    3. Finally, let's throw in some rounding. Here we will use the printf function to round to 4 decimal places. Note that the 3.14159... rounds now to 3.1416. Since we are rounding, we no longer need to use scale=10 to truncate to 10 decimal places, so we'll just remove that part. Here's the end solution:

      pi=$(printf %.4f $(echo "4*a(1)" | bc -l)); echo $pi
      3.1416
      
  2. Measuring and printing run time:

    Measuring and printing a program's run time is another really great application and demo of the above techniques.

    (See also my other answer here).

    Here is how. Note that dt_min gets rounded from 0.01666666666... to 0.017:

    start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); echo "dt_sec = $dt_sec; dt_min = $dt_min"
    dt_sec = 1; dt_min = 0.017
    

Related:

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
5

While you can't use floating point division in Bash you can use fixed point division. All that you need to do is multiply your integers by a power of 10 and then divide off the integer part and use a modulo operation to get the fractional part. Rounding as needed.

#!/bin/bash

n=$1
d=$2

# because of rounding this should be 10^{i+1}
# where i is the number of decimal digits wanted
i=4
P=$((10**(i+1)))
Pn=$(($P / 10))
# here we 'fix' the decimal place, divide and round tward zero
t=$(($n * $P / $d + ($n < 0 ? -5 : 5)))
# then we print the number by dividing off the interger part and
# using the modulo operator (after removing the rounding digit) to get the factional part.
printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn))
G. Allen Morris III
  • 1,012
  • 18
  • 30
5

I know it's old, but too tempting. So, the answer is: you can't... but you kind of can. let's try this:

$IMG_WIDTH=1024
$IMG2_WIDTH=2048

$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"

Like that, you get 2 digits after the point, truncated (call it rounding to the lower) in pure bash (no need to launch other processes). Of course, if you only need one digit after the point you multiply by 10 and do modulo 10.

What this does:

  • first $((...)) does integer division;
  • second $((...)) does integer division on something 100 times larger, essentially moving your 2 digits to the left of the point, then (%) getting you only those 2 digits by doing modulo.

Bonus track: bc version × 1000 took 1.8 seconds on my laptop, while the pure bash one took 0.016 seconds.

starfry
  • 9,273
  • 7
  • 66
  • 96
  • Your "solution" will not work when the result is less than 10 in the "second" part. Try with, `IMG_WIDTH=103` and `IMG2_WIDTH=100` for example. – FedKad May 15 '21 at 07:41
4

It's not really floating point, but if you want something that sets more than one result in one invocation of bc...

source /dev/stdin <<<$(bc <<< '
d='$1'*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a='$1'*'$1'*3.1415926535897932384626433832795
print "a=",a,"\n"
')

echo bc radius:$1 area:$a diameter:$d

computes the area and diameter of a circle whose radius is given in $1

4

There are scenarios in wich you cannot use bc becouse it might simply not be present, like in some cut down versions of busybox or embedded systems. In any case limiting outer dependencies is always a good thing to do so you can always add zeroes to the number being divided by (numerator), that is the same as multiplying by a power of 10 (you should choose a power of 10 according to the precision you need), that will make the division output an integer number. Once you have that integer treat it as a string and position the decimal point (moving it from right to left) a number of times equal to the power of ten you multiplied the numerator by. This is a simple way of obtaining float results by using only integer numbers.

Daniel J.
  • 308
  • 2
  • 12
4

For those trying to calculate percentages with the accepted answer, but are losing precision:

If you run this:

echo "scale=2; (100/180) * 180" | bc

You get 99.00 only, which is losing precision.

If you run it this way:

echo "result = (100/180) * 180; scale=2; result / 1" | bc -l

Now you get 99.99.

Because you're scaling only at the moment of printing.

Refer to here

Wadih M.
  • 12,810
  • 7
  • 47
  • 57
3

Use calc. It's the easiest I found example:

calc 1+1

 2

calc 1/10

 0.1
2

** Injection-safe floating point math in bash/shell **

Note: The focus of this answer is provide ideas for injection-safe solution to performing math in bash (or other shells). Of course, same can be used, with minor adjustment to perform advanced string processing, etc.

Most of the solution that were by presented, construct small scriptlet on the fly, using external data (variables, files, command line, environment variables). The external input can be used to inject malicious code into the engine, many of them

Below is a comparison on using the various language to perform basic math calculation, where the result in floating point. It calculates A + B * 0.1 (as floating point).

All solution attempt avoid creating dynamic scriptlets, which are extremely hard to maintain, Instead they use static program, and pass parameters into designated variable. They will safely handle parameters with special characters - reducing the possibility of code injection. The exception is 'BC' which does not provide input/output facility

The exception is 'bc', which does not provide any input/output, all the data comes via programs in stdin, and all output goes to stdout. All calculation are executing in a sandbox, which does not allow side effect (opening files, etc.). In theory, injection safe by design!

A=5.2
B=4.3

# Awk: Map variable into awk
# Exit 0 (or just exit) for success, non-zero for error.
#
awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'

# Perl
perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"

# Python 2
python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"

# Python 3
python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"

# BC
bc <<< "scale=1 ; $A + $B * 0.1"
WiringHarness
  • 362
  • 1
  • 2
  • 10
dash-o
  • 13,723
  • 1
  • 10
  • 37
  • for python3 with arbitrary arguments: `python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B"` "4200.0" ==> 4205.63 – WiringHarness Apr 28 '20 at 01:01
2

As others have indicated, bash does not have built-in floating-point operators.

You can implement floating-point in bash, even without using calculator programs like bc and awk, or any external programs for that matter.

I'm doing exactly this in my project, shellmath, in three basic steps:

  1. Break the numbers down into their integer and fractional parts
  2. Use the built-in integer operators to process the parts separately while being careful about place-value and carrying
  3. Recombine the results

As a teaser, I've added a demo script that calculates e using its Taylor series centered at x=0.

Please check it out if you have a moment. I welcome your feedback!

Clarity_20
  • 143
  • 5
  • 1
    That sounds like an interesting exercise, but is it practical? The usual objective of preferring to do data processing tasks natively in shell script instead of with an external program is to avoid the overhead of launching a new process. But that stands against the shell's basic slowness for many such tasks. Under what circumstances does your shell implementation outperform `bc` (for example)? – John Bollinger Dec 06 '20 at 16:42
  • 2
    Thanks for the question. I've added some information about this to the shellmath README. I believe it's practical because of my timing experiments, which I've captured in `timingData.txt`. First off, I've been careful to use time-efficient scripting practices (details available in the project), but I think the real key is that you can run `shellmath` without forking a subshell. `shellmath` is a family of functions that write their result to a shell variable. OTOH, since `bc` is an executable, you have to subshell it to capture the results. – Clarity_20 Jan 25 '21 at 12:17
  • Kinda cool ! I like the idea – lumpidu Feb 22 '23 at 11:30
1

Dividend = Divisor × Quotient + Remainder

Lets just calculate the quotient and remainder. As well as concatenate those strings in a variable.

New way valid only to log_decimal divisors:

function main() {
  bar=10030
  divisor=100
  # divisor=50

  quotient=$((bar / divisor))
  # remainder=$((bar - v_int * divisor))
  remainder=$((bar % divisor))
  remainder_init=$remainder

  printf "%-15s --> %s\n" "quotient" "$quotient"
  printf "%-15s --> %s\n" "remainder" "$remainder"

  cnt=0
  while :; do
    remainder=$((remainder * 10))
    aux=$((remainder / divisor))
    printf "%-15s --> %s\n" "aux" "$aux"
    [[ aux -ne 0 ]] && break
    ((cnt += 1))
    printf "%-15s --> %s\n" "remainder" "$remainder"
  done
  printf "%-15s --> %s\n" "cnt" "$cnt"
  printf "%-15s --> %s\n" "aux" "$aux"

  printf $quotient
  printf "."
  for i in $(seq 1 $cnt); do printf "0"; done
  printf $remainder_init
}
clear
main

Old wrong way:

bar=1234 \
&& divisor=1000 \
    && foo=$(printf "%s.%s" $(( bar / divisor )) $(( bar % divisor ))) \
    && printf "bar is %d miliseconds or %s seconds\n" $bar $foo

Output: bar is 1234 miliseconds or 1.234 seconds

Xopi García
  • 359
  • 1
  • 2
  • 9
1

Bash can calculate floating point results just fine without any other programs.

Bash independently even can calculate π to the ninth decimal place accurately.

Example:

calc=104348/33215

accuracy=9

calc99p9=$((10**$accuracy))*$calc
result99p9=$((calc99p9))
result=${result99p9: -${#result99p9}: -$accuracy}.${result99p9: -$accuracy}

echo Bash calculated pi to be $result

results in

Bash calculated pi to be 3.141592653
0

here is awk command: -F = field separator == +

echo "2.1+3.1" |  awk -F "+" '{print ($1+$2)}'
koolwithk
  • 685
  • 8
  • 14
0

how precise do you need the output to be ? if an approximation via binning is already acceptable for your use case, you can even go one step further and take advantage of POSIX exit codes [0:256) (all other integers mod'd back to that range).

eg : in gawk/nawk/mawk-1, it already gives me epoch seconds down to the integer level, but I wanted to expand that to extract near-milliseconds precision but not overly pedantic about it, i run this command in a POSIX shell

exit $(( 10#` gdate +%5N ` * 256 / 100000 ))

directly assigning a 5-digit integer representing 0.xxxxxx output of gnu-date into 1 of 256 bins, then un-doing that 256 once awk obtains the exit code of the system() call, i.e. the selected bin #. I found this approach to have lower overhead than using a full getline call.

This method also directly captures the output into the POSIX exit code instead of also having an extra terminal print out.

(the shell arithmetic auto floors it to integer if written this way instead of * 0.0256). Putting together into an awk function, it would resemble this. The 10# is to force base-10 to prevent posix shell interpreting "01733" as an octal number.

function msecs() {     # n x 2**-8 = n divided by 256

    return 2^-8 * \
           system( "exit \44\50\50 "      \
                   " 10\43\140 gdate \53"  \
                   "%5N\140 \52 " \
                   "256 \57 100000 \51\51" )
}
  • for my own code, i apply another 0.6% haircut to account for shell-overhead.
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11
0

Let us take an example to undertsand, if u want to find average of n array elements (Ofcourse the average will be in float/decimals)

declare -a arr
echo "How many numbers you want to enter?"
read n
echo "Enter the Array Elements"
for(( i=0 ; i<$n ; i++))
do
      read array_elements
      arr[$i]="$array_elements"
done
sum=0
for i in "${arr[@]}"
do
     #sum and avg
     sum=$(($sum + $i))
     #average will come in decimals
     avg=`echo $sum / $n | bc -l`
done
# Output results:
printf "Average of Array Elements %.2f:" $avg

So we will use "| bc -l" to do floating calculations

Mr. T-REX
  • 124
  • 1
  • 6
0

You can use python

RESULT=$(python -c "print($IMG_WIDTH/$IMG2_WIDTH)")
Michael Hall
  • 2,834
  • 1
  • 22
  • 40