【问题标题】:How to use bc in a bash while loop condition statement?如何在 bash while 循环条件语句中使用 bc?
【发布时间】:2017-08-19 14:57:48
【问题描述】:

我正在编写一个简单的 bash 脚本来计算公式 C=1-(p^n) 中所需的最小值 p。 C和p是用户输入的浮点数。

例如,如果 C=0.36 和 p=0.8,那么我的程序应该为 n 的值返回 2,因为 1-(0.8^2)=0.36

我的代码如下。请注意:我在我的 while 循环条件语句中将|bc 放在了许多不同的位置,并且每次出现错误时。如您所见,我尝试的最后一个位置是在两个右括号之间。

我收到以下错误:

预期的操作数(错误标记是“.36”)

#!/bash/bin

echo "Enter I/O fraction time:"
read ioINPUT
echo "Enter expect CPU utilization:"
read uINPUT
n=1

function cpuUTIL {
    x='scale=3; 1-$ioINPUT**$n'|bc
}

while [[ cpuUTIL -lt $uINPUT ]|bc]; do
    n+=1
    x='scale=3; 1-$ioINPUT**$n'|bc
done
echo $c

如何在 bash 脚本 while 循环条件语句中正确使用 bc?

【问题讨论】:

  • 代码的一些问题:1./bash/binspoonerism。 2. 变量名应该是cpn,而不是$ioINPUT$uINPUT$x . 3. 最后一行是echo $c,但从未分配过$c。 4. 测试仅整数 -lt 与十进制值的比较。 5.函数cpuUTIL不能用-lt测试。 6. 变量赋值不产生输出,因此将它们传递到bc 没有任何效果。 7.]|bc] 错字。 8. while 测试不会受到该循环中的内容的影响,并且如果启动必须永远运行。
  • 感谢您的提示。 1 和 3 发生是因为我赶时间并且很累。我道歉。唯一我不明白的问题是 2:为什么我的变量要命名为 c、p 和 n?
  • 因为它是一个简单的程序,并且被建模的公式使用这些变量,所以程序更容易效仿。如果代码必须有长名称,那么最好使用这些等式字母建模的任何属性的名称。

标签: bash shell while-loop conditional-statements bc


【解决方案1】:

在 cmets 中指出了一些问题。这是您尝试的修复版本:

#!/bin/bash

cpuUTIL () {
    bc <<< "scale = 3; 1 - $ioINPUT ^ $n"
}

read -p "Enter I/O fraction time: " ioINPUT
read -p "Enter expect CPU utilization: " uINPUT
n=1

while (( $(bc <<< "$(cpuUTIL) < $uINPUT") )); do
    (( ++n ))
    x=$(bc <<< "scale = 3; 1 - $ioINPUT ^ $n")
done

echo $x

评论:

  • #!/bin/bash,不是#!/bash/bin
  • echoread 可以缩短为 read -p
  • function cpuUTIL 的便携性不如 cpuUTIL ()
  • 单引号防止参数扩展; bc 命令必须使用双引号
  • 我使用了 here-strings (&lt;&lt;&lt;) 而不是管道以避免创建子外壳
  • bc 中的“Power of”是^ 而不是**
  • while 条件很复杂:在(( )) 中使用嵌套命令替换,它将 bc 语句的输出(如果比较成立,则为 1,如果不成立,则为 0)为 Bash
  • n+=1 将字符串 1 附加到变量 n 的内容中(除非它被声明为带有 declare -i 的整数,但这很奇怪),所以你必须使用类似算术上下文的东西,(( ++n ))
  • 最后的语句应该是echo $x

但是,正如karakfa's answer 所演示的,您可以直接执行此操作。在 bc 中,它看起来像这样:

$ p=0.8
$ C=0.36
$ bc -l <<< "scale = 3; l(1-$C) / l($p)"
2.000

bc -l 定义了数学库,其中包含(以及其他一些)自然对数 l(x)

【讨论】:

  • 由于bc有变量,完全可以在bc中完成:bc -l &lt;&lt;&lt; "p=0.8 ; c=0.36 ; scale = 3 ; l(1-c) / l(p)"
  • @agc,当然,但仍应提示用户提供值而不是使用两个魔术常量,所以我假设这发生在 bc 之外,并且 bc 命令是 shell 脚本的一部分.当然,您也可以使用 read() 提示 bc 中的用户(如果您使用 GNU bc)并使整个事情成为 bc 可执行文件。
【解决方案2】:

您可以迭代并找到一个值,但为什么呢?这里有一个更好的方法

awk -v p=0.8 -v C=0.36 'BEGIN{print log(1-C)/log(p)}'

该值也将是,通常是浮点数,您可以通过用int() 包装日志比率来获得下限

【讨论】:

  • 我最初想使用对数,但无法弄清楚如何用 bc 实现它们,所以我选择了迭代。在发布这个问题(并放弃 bc)后,我才开始阅读有关 awk 的信息。感谢您的帮助。
【解决方案3】:

使用 GNU bc:

#!/usr/bin/bc -ql
scale=3
print "Enter I/O fraction time: "
p=read()
print "Enter expected CPU utilization: "
c=read()
l(1-c)/l(p)
quit

将以上内容保存到foo.bc,运行chmod +x foo.bc,然后使用./foo.bc执行。

或者没有提示,来自bash

bc -l <<< "p=0.8;c=0.36;scale=3;l(1-c)/l(p)"

【讨论】:

    猜你喜欢
    • 2019-11-07
    • 2014-01-21
    • 2015-06-15
    • 2011-10-23
    • 2013-03-26
    • 2018-01-21
    • 2019-01-14
    • 1970-01-01
    • 2013-01-01
    相关资源
    最近更新 更多