Reputation: 2419
This is a hackerrank problem:
As a brief summary, you need to sum up a predefined number of integers, then compute the average and print it with 3 digits precision.
I came up with the following code:
read number_of_ints;
sum=0
for number in $(seq 1 $number_of_ints); do
read number
sum=$(($sum+$number))
done
printf "%.3f\n" | bc -l <<< $sum/$number_of_ints
printf "%.3f\n" $(echo "$sum/$number_of_ints" | bc -l)
However, printf "%.3f\n" | bc -l <<< $sum/$number_of_ints
blatantly ignores my format string and simply outputs it with 20 digit precision.
Meanwhile printf "%.3f\n" $(echo "$sum/$number_of_ints" | bc -l)
does exactly what I want.
I get that the 20 precision digits are rooted in the fact that bc -l preloads a math library, but shouldn't printf "%.3f" still cut this down to three digits?
Upvotes: 0
Views: 829
Reputation: 10123
A solution in pure bash
, without resorting to bc
#!/bin/bash
sum=0
read n
for ((i = 0; i < n; ++i)); do read m; ((sum += m)); done
sign=1
if ((sum < 0)); then sign=-1; ((sum = -sum)); fi
m=$(( (sum * 10000 / n + 5) / 10 ))
printf '%d.%03d\n' $((m / 1000 * sign)) $((m % 1000))
Upvotes: 0
Reputation: 15273
The problem is that you aren't using printf
correctly. printf
expects a format string followed by as many strings as it gets, and it tries to parse them sanely according to the format. You have provided a format, but NO inputs, so it is likely just printing the requested newline to the pipe you set up behind it.
The bc
now has two streams defined on stdin, and is ignoring the pipe in favor of the here-string.
printf "%.3f\n" | bc -l <<< $sum/$number_of_ints # two inputs
c.f. this post for a similar issue.
...But you don't need printf
at all. See https://linux.die.net/man/1/bc
bc -l <<< "scale=3;$sum/$number_of_ints"
You could, in fact, code the whole thing in bc
.
#!/usr/bin/bc
print "\nHow many numbers shall we average? "
scale=3
cnt=read()
c=cnt
while ( c ) {
c=c-1
print "\nEnter a number: "
n=read()
t=t+n
}
print "\nTotal: ", t, "\n"
print "Average: ", t/cnt, "\n"
quit
Then run it.
$: ./bcavg
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
How many numbers shall we average? 3
Enter a number: 2
Enter a number: 7
Enter a number: 9
Total: 18
Average: 6.000
Upvotes: 3
Reputation: 295363
The code as given doesn't actually convey the output from bc
to the command line of printf
.
One way to span that gap would be with xargs
:
bc -l <<<"$sum/$number_of_ints" | xargs printf '%.3f\n'
Upvotes: 2