bash中的printf忽略格式

时间:2020-09-16 12:58:27

标签: bash printf

这是一个hackerrank问题:

Compute the average

作为一个简短的摘要,您需要对预定义的整数进行求和,然后计算平均值并以3位精度打印它。

我想到了以下代码:

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)

但是,printf "%.3f\n" | bc -l <<< $sum/$number_of_ints公然忽略了我的格式字符串,只是以20位精度输出它。 同时printf "%.3f\n" $(echo "$sum/$number_of_ints" | bc -l)正是我想要的。

我知道20个精度数字植根于bc -l预加载数学库这一事实,但是printf“%.3f”难道还不能将其减少到三位数吗?

3 个答案:

答案 0 :(得分:3)

问题是您没有正确使用printfprintf期望一个格式字符串,后跟尽可能多的字符串,并尝试根据格式合理地解析它们。您提供了一种格式,但没有输入,因此很可能只是将请求的换行符打印到您在其后面设置的管道中。

bc现在在stdin上定义了两个流,并且忽略了使用here字符串的管道。

printf "%.3f\n" | bc -l <<< $sum/$number_of_ints # two inputs

c.f。 this post处理类似问题。

...但是您根本不需要printf。参见https://linux.die.net/man/1/bc

bc -l <<< "scale=3;$sum/$number_of_ints"

实际上,您可以在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

然后运行它。

$: ./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

答案 1 :(得分:2)

给出的代码实际上并未将bc的输出传递到printf的命令行。

一种弥补这一差距的方法是使用xargs

bc -l <<<"$sum/$number_of_ints" | xargs printf '%.3f\n'

答案 2 :(得分:0)

bash中的解决方案,不求助于 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))
相关问题