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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:25:16  来源:igfitidea点击:

Floating point comparison with variable in bash

bashif-statementfloating-point

提问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 foundis what the terminal outputs.

PS:这[0.43: command not found是终端输出的内容。

回答by user000001

Bash can't handle floats. Pipe to bcinstead:

Bash 无法处理浮动。bc改为管道:

if [ $(echo " $test > $k" | bc) -eq 1 ]

The error you see though is because the testcommand (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 POSIXcompiant.

如果关系为假,关系表达式的计算结果为 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. ntestor mynumericcomparisonor even [[[.
  • printfis 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 printfformats.
  • The 10#at the beginning of each variable inside the casestatement 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

另见:http: //mywiki.wooledge.org/BashFAQ/022