Reputation: 49
I want to calculate the percentage of a few numbers upto 2 decimal places. Since my total count is pretty high, dividing 100 by it gives a really small number (0.000..) so for this step I have a large scale of 10. The second step where i multiply the resulting number to calculate the percentage uses scale as 2, but it is ignored as bc uses the first scale of 10. This is the code I have:
mul=$(bc <<< "scale=10; (100/$t)")
while read -r num var
do
perc=$(bc <<< "scale=2; ($num*$mul)")
printf "$var\t$num\t$perc\n" >> ofile
done < counts
How can I get the second calculation to follow the scale and print up to 2 decimal places?
Upvotes: 3
Views: 1088
Reputation: 421
First of all, the second bc can't use the scale of the first bc, they are two separate instances, bc will not remember the setting of a different process. It's just a coincidence that it ends up being scale 10 at the second run.
However, as JRFerguson wrote, scale is differently calculated for multiplication and division. But if you add a division by 1 to the end of your calculation, the scale settings will be taken into account:
perc=$(bc <<< "scale=2; ($num*$mul/1)")
Upvotes: 0
Reputation: 248
You can sort this problem out by using the following "kludge":
a=3.2222222222
b=24.30123
foo=$(bc <<< "x = $a * $b; scale=2; (x * 100) / 100;")
echo $foo
This code will print out the following output:
78.30
The idea here is that the result of the calculation (x * 100) / 100
is going to be the same number as $a * $b
(78.303963332793306
), but the scale that's going to be applied to it this time will be 2 which in effect will truncate everything you have after two decimal places making it 78.30.
For the reason what happens with the scale of a number that you get as a result of multiplication of two other numbers, see JRFerguson's answer.
The code, in fact, can be made even shorter:
foo=$(bc <<< "scale=2; ($a * $b) / 1")
This is because the new number that you'll get is gong to inherit the global scale of 2 that you had specifically set up.
Upvotes: 1
Reputation: 7526
The scale
(total number of decimal digits after the decimal point) used with bc operates differently depending on the arithmetic operation involved.
expression*expression
The result shall be the product of the two expressions. If a and b are the scales of the two expressions, then the scale of the result shall be:
min(a+b,max(scale,a,b))
expression/expression
The result shall be the quotient of the two expressions. The scale of the result shall be the value of scale.
This is the reason for the differing behavior between your division and your multiplication in your code.
Upvotes: 1
Reputation: 241968
Format the numbers via printf:
printf '%s\t%s\t%.2f\n' "$var" "$num" "$perc" >> ofile
Upvotes: 1