How to calculate extra large numbers with bc in bash - bash

I have a file with 1800 lines that look like this
600.76
600.66
700.44
566.66
Ect..
I made a bash script to calculate the mean.
Now I first made a variable to count the total column lines like:
Lines="$(awk 'END{print NR}' file.txt)"
Then another variable for the sum of that column like this:
Sum="$(awk '{s+1=$1}END {print s}' file.txt)"
Lastly I'm finding the mean like this:
Echo "scale=2 ; $Sum / $Lines" | bc
With debugging enabled It returns:
+echo 'scale=2 ; 1.72161e+06 / 1800'
(Standard_1): syntax error
I realize now bc doesn't do scientific notation but how do I get around this.
I'm OK with short handing the decimal by restricting it to 2 or 3 places.

Unnecessary to use awk. Simple oneliner can do the job.
echo "scale=2; ("$(paste -sd+ file.txt)")"/$(wc -l <file.txt)|bc

Use bc -l for both summation and final division:
sum=0
count=0
while read number; do
number=$(printf "%f\n" $number) # get rid of scientific notation
sum=$(echo "$sum" '+' "$number" | bc -l)
count=$((count + 1))
done < input
avg=$(echo $sum / $count | bc -l)
echo $avg

Related

Bash round whole numbers up, down or to nearest hundreds

There is a range of whole positive numbers like
827818
6574762
685038
55326902
What I need, for example, to round down to hundreds to get accordingly
827800
6574700
685000
55326900
Many ideas how to round up, down or nearest hundreds using Javascript, for example
Math.floor(number / 100) * 100;
but is it possible to do the same in Bash ?
It's not entirely clear what is meant by "in Bash", but perhaps one of :
$ cat input
827818
6574762
685038
55326902
$ awk '{printf "%d00\n", $0 / 100}' input
827800
6574700
685000
55326900
or (if all the values are greater than 100!):
while read x; do echo "${x%[0-9][0-9]}00"; done < input
If you want to handle the case where values are less than 100 and deal with negative values, you could do:
while read x; do if test "${x#-}" -gt 100; then echo "${x%[0-9][0-9]}00"; else echo 0; fi; done < input
but it's almost certainly better to stick with awk.
To round to the nearest 100, use (number + 50) / 100 * 100.
You can modify each line to this calculation, then run those expressions through bc to evaluate them.
sed 's|.*|(&+50)/100*100|' file | bc
For rounding down you can also rev the full number and use cut -c 1-2 on the output, which you can then rev again to obtain the full number's last two digits. Then you can do calc or bc (full number - first output) to round down to nearest 100.
Or you can remove the last two digits of the full number with bc using scale=0 (or no scale) and divide by 100, after which you can just multiply by 100 again;
DIV_100=$( echo "123456789/100" | bc ) && echo "$DIV_100*100" | bc
and in loop
while read -r line; do
echo "$line" > full_number_1.txt
FULL_NUMBER=$(<full_number_1.txt)
DIV_100=$( echo "$FULL_NUMBER / 100" | bc )
echo "$DIV_100 * 100" | bc >> output_file
done < input.txt
Or use echo ${...%??}
echo "${number%??}*100" | bc
..loop..
while read -r line; do
echo "${line%??}*100" | bc >> output
done < input.txt
Many options here for rounding down.
Rounding up will require some alterations but is equally possible in many ways. For example:
DIV_100=$( echo "123456789/100" | bc ) && echo "($DIV_100*100)+100" | bc
and in loop
while read -r line; do
echo "$line" > full_number_1.txt
FULL_NUMBER=$(<full_number_1.txt)
DIV_100=$( echo "$FULL_NUMBER / 100" | bc )
echo "($DIV_100 * 100)+100" | bc >> output_file
done < input.txt
or with echo ${...%??}
echo "(${number%??}*100)+100" | bc
..loop..
while read -r line; do
echo "(${line%??}*100)+100" | bc >> output
done < input.txt

calculate percentage increase/decrease between 2 numbers with many decimals in bash

I need to calculate the percentage increase/decrease between 2 numbers in a bash script, and I need at 2 decimals after . The numbers will have many decimals (eg. 684.0800000, 683.7550000).
I`ve seen bc can do that, but i cannot get it to work.kind regards
$ echo 684.0800000 683.7550000 | awk '{printf "%.2f%\n", 100*($2/$1-1)}'
-0.05%
that is 0.05% decrease from first to second, which is -0.0475 rounded to two decimal points.
Use the bc scale variable to determine the precision
x=684.0800000
y=683.7550000
echo "scale=2; 100 * ($y - $x) / $x" | bc
-.04
Using bc and formating output with printf:
$ a=684.0800000
$ b=683.7550000
$ printf '%.2f\n' $(echo "100*$b/$a-100" | bc -l)
-0.05
With more digestable values:
$ a=5
$ b=2
$ printf '%.2f\n' $(echo "100*$b/$a-100" | bc -l)
-60.00

Bash how to store a division to a variable

I am trying to calculate below formula and store the value to a variable.
The pseudo code should look like:
a=10
b=5
c=$(((($a-$b)/52)) | bc -l)
echo $c
The result is empty. I couldn't figure out the syntax using bc. Please help me use bc instead of awk or other method.
There are two things you need to be aware of. The first is that bc uses standard input for expressions so you would need to actually pipe your expression through it, or use the <<< redirection operator, one of:
c=$(echo "($a - $b) / 52" | bc)
c=$(bc <<< "($a - $b) / 52")
The <<< method is specific to bash and ksh (an possibly others, but I'm not really au fait with them). The other method can be used in most shells.
Secondly, you should be careful when using big numbers for this since bc has the annoying habit of splitting them across lines:
pax$ x=999999999999999999999999999999999999999999999999999999999999999999999
pax$ echo "$x / 7" | bc
14285714285714285714285714285714285714285714285714285714285714285714\
2
In order to avoid this, you need to change the line length:
pax$ echo "$x / 7" | BC_LINE_LENGTH=0 bc
142857142857142857142857142857142857142857142857142857142857142857142
You can use this:
a=10
b=5
c=$(bc -l <<< "($a-$b)/52")
echo "$c"
.09615384615384615384
Or by setting a scale of 3:
c=$(bc -l <<< "scale=3; ($a-$b)/52")
echo "$c"
.096

How to display number to two decimal places, even zero .00 using BC or DC [duplicate]

Greetings!
I uses bс to make some calculations in my script. For example:
bc
scale=6
1/2
.500000
For further usage in my script I need "0.500000" insted of ".500000".
Could you help me please to configure bc output number format for my case?
In one line:
printf "%0.6f\n" $(bc -q <<< scale=6\;1/2)
Just do all your calculations and output in awk:
float_scale=6
result=$(awk -v scale=$floatscale 'BEGIN { printf "%.*f\n", scale, 1/2 }')
As an alternative, if you'd prefer to use bc and not use AWK alone or with 'bc', Bash's printf supports floating point numbers even though the rest of Bash doesn't.
result=$(echo "scale=$float_scale; $*" | bc -q 2>/dev/null)
result=$(printf '%*.*f' 0 "$float_scale" "$result")
The second line above could instead be:
printf -v $result '%*.*f' 0 "$float_scale" "$result"
Which works kind of like sprintf would and doesn't create a subshell.
Quick and dirty, since scale only applies to the decimal digits and bc does not seem to have a sprintf-like function:
$ bc
scale = 6
result = 1 / 2
if (0 <= result && result < 1) {
print "0"
}
print result;
echo "scale=3;12/7" | bc -q | sed 's/^\\./0./;s/0*$//;s/\\.$//'
I believe here is modified version of the function:
float_scale=6
function float_eval()
{
local stat=0
local result=0.0
if [[ $# -gt 0 ]]; then
result=$(echo "scale=$float_scale; $*" | bc -q | awk '{printf "%f\n", $0}' 2>/dev/null)
stat=$?
if [[ $stat -eq 0 && -z "$result" ]]; then stat=1; fi
fi
echo $result
return $stat
}
Can you put the bc usage into a little better context? What are you using the results of bc for?
Given the following in a file called some_math.bc
scale=6
output=1/2
print output
on the command line I can do the following to add a zero:
$ bc -q some_math.bc | awk '{printf "%08f\n", $0}'
0.500000
If I only needed the output string to have a zero for formatting purposes, I'd use awk.

How to add an integer number and a float number in a bash shell script

I have two numbers:
value1=686
value2=228.35
I am not able to add an integer and a float. Please help me out to get the result.
I am running it in bash.
echo 1 + 3.5 | bc
awk "BEGIN {print 1+3.5; exit}"
python -c "print 1+3.5"
perl -e "print 1+3.5"
Just replace the numbers with your variables, eg: echo $n1 + $n2 | bc
If you have the bc language installed, you can do the following:
#!bin/bash
numone=1.234
numtwo=0.124
total=`echo $numone + $numtwo | bc`
echo $total
If you don't have bc, then you can try with awk. Just in one single line:
echo 1.234 2.345 | awk '{print $1 + $2}'
There are plenty of other options, also. Like python, perl, php....
Bash doesn't have floating-point types, but you can use a calculator such as bc:
a=686
b=228.35
c=`echo $a + $b | bc`
echo "$c"
#!/bin/Bash
echo "Enter the two numbers to be added:"
read n1
read n2
answer=$(($n1+$n2))
echo $answer

Resources