bash bash中与变量的浮点比较
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15224581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Floating point comparison with variable in bash
提问by user1983400
I want to compare a floating point variable to an integer. I know this is not the best to do with bash, but my whole script is already written in bash. $number can be any integer. If it below or equal 50, I want output1, for all others I want an output with the other variable k. This is what I have so far:
我想将浮点变量与整数进行比较。我知道这对 bash 来说不是最好的,但是我的整个脚本已经用 bash 编写了。$number 可以是任何整数。如果它低于或等于 50,我想要 output1,对于所有其他人,我想要一个带有其他变量 k 的输出。这是我到目前为止:
number=43
test=$(echo "scale=2; $number/50" | bc -l)
echo "$test"
for k in {1..5}
do
if ["$test" -le 1]
then echo "output"
elif ["$test" -gt $k]
then echo "output$k"
fi
done
If I try with test=0.43, the first loop does not even work. I think it has to do with an integer and a floating point comparison but cannot make it work.
如果我尝试使用 test=0.43,第一个循环甚至不起作用。我认为它与整数和浮点比较有关,但无法使其工作。
Anything I am missing?
我缺少什么吗?
PS:this [0.43: command not found
is what the terminal outputs.
PS:这[0.43: command not found
是终端输出的内容。
回答by user000001
Bash can't handle floats. Pipe to bc
instead:
Bash 无法处理浮动。bc
改为管道:
if [ $(echo " $test > $k" | bc) -eq 1 ]
The error you see though is because the test
command (i.e. the [
) needs spaces before and after
您看到的错误是因为test
命令(即[
)前后需要空格
It is even better to use (( ... ))
since you compare numbers like this:
(( ... ))
由于您比较这样的数字,因此使用效果更好:
if (( $(bc <<< "$test > $k") ))
The part in the loop should look like this:
循环中的部分应如下所示:
if (( $(bc <<< "$test <= 1") ))
then
echo "output"
elif (( $(bc <<< "$test > $k") ))
then
echo "output$k"
fi
Relational expressions evaluate to 0, if the relation is false, and 1 if the relation is true [source]. Note however that is a behavior of GNU bc
, and it is not POSIX
compiant.
如果关系为假,关系表达式的计算结果为 0,如果关系为真,则计算结果为 1 [来源]。但是请注意,这是 的行为GNU bc
,并且不POSIX
兼容。
回答by ghoti
Kind of an old question, but it bears an additional answer I think.
有点老问题,但我认为它有一个额外的答案。
While piping to a higher precision calculator (bc or dc) works, it is at the cost of a fork and a an extra process, since those calculators are not built in to bash. One thing that IS built in, though, is printf
. So if you can deal with your numbers being within a particular number of decimal places, you can "fake" floating point comparisons, with a function like this:
虽然通过管道连接到更高精度的计算器(bc 或 dc)是有效的,但它是以 fork 和额外过程为代价的,因为这些计算器不是内置到 bash 中的。但是,IS 内置的一件事是printf
. 因此,如果您可以处理位于特定小数位数内的数字,则可以使用如下函数“伪造”浮点比较:
#!/usr/bin/env bash
function [[[ () {
local LANG=C lhs rhs
printf -v lhs '%07.3f' ""; lhs=${lhs/./}
printf -v rhs '%07.3f' ""; rhs=${rhs/./}
case "" in
-lt) return $(( ! ( 10#$lhs < 10#$rhs ) )) ;;
-le) return $(( ! ( 10#$lhs <= 10#$rhs ) )) ;;
-eq) return $(( ! ( 10#$lhs == 10#$rhs ) )) ;;
-ge) return $(( ! ( 10#$lhs >= 10#$rhs ) )) ;;
-gt) return $(( ! ( 10#$lhs > 10#$rhs ) )) ;;
esac
}
number=${1:-43}
test=$(dc -e "2k $number 50 / p")
echo "$test"
for k in {1..5}; do
if [[[ "$test" -le 1 ]]]; then
echo "output"
elif [[[ "$test" -gt "$k" ]]]; then
echo "output $k"
fi
done
A few things to consider here.
这里需要考虑一些事情。
- I've named the function
[[[
to be cute. You can name it whatever you like.ntest
ormynumericcomparison
or even[[[
. printf
is an internal function within bash, so despite the fact that it's on your path, it doesn't cost a fork.- As it stands, the function supports numbers up to 999.999. If you need higher numbers (or more precision), adjust the
printf
formats. - The
10#
at the beginning of each variable inside thecase
statement is to force the comparison to happen at base 10, since a zero-padded number might otherwise be interpreted as octal.
- 我已经将该函数命名
[[[
为可爱的。你可以随意命名它。ntest
或者mynumericcomparison
甚至是[[[
。 printf
是 bash 中的一个内部函数,因此尽管它在您的路径上,但它不需要分叉。- 就目前而言,该函数支持高达 999.999 的数字。如果您需要更高的数字(或更高的精度),请调整
printf
格式。 - 将
10#
在内部的各个变量的开头case
语句是迫使比较基部10发生的,因为零填充数字可能被解释为八进制。
See also: http://mywiki.wooledge.org/BashFAQ/022