如何在Bash中比较两个浮点数?

如何在Bash中比较两个浮点数?,bash,floating-point,comparison,numbers,Bash,Floating Point,Comparison,Numbers,我正在努力比较bash脚本中的两个浮点数。我必须改变一些变量,例如 let num1=3.17648e-22 let num2=1.5 现在,我只想对这两个数字做一个简单的比较: st=`echo "$num1 < $num2" | bc` if [ $st -eq 1]; then echo -e "$num1 < $num2" else echo -e "$num1 >= $num2" fi st=`e

我正在努力比较bash脚本中的两个浮点数。我必须改变一些变量,例如

let num1=3.17648e-22
let num2=1.5
现在,我只想对这两个数字做一个简单的比较:

st=`echo "$num1 < $num2" | bc`
if [ $st -eq 1]; then
  echo -e "$num1 < $num2"
else
  echo -e "$num1 >= $num2"
fi
st=`echo“$num1<$num2”|公元前`
如果[$st-等式1];然后
echo-e“$num1<$num2”
其他的
echo-e“$num1>=$num2”
fi

不幸的是,我在正确处理num1时遇到了一些问题,num1可以是“e格式”。

bash只处理整数数学 但您可以按如下方式使用
bc
命令:

$ num1=3.17648E-22
$ num2=1.5
$ echo $num1'>'$num2 | bc -l
0
$ echo $num2'>'$num1 | bc -l
1

请注意,指数符号必须为大写

对于非整数数学,最好使用
awk
。您可以使用此bash实用程序函数:

numCompare() {
   awk -v n1="$1" -v n2="$2" 'BEGIN {printf "%s " (n1<n2?"<":">=") " %s\n", n1, n2}'
}
# get version of GNU tool
toolversion() {
    local prog="$1" operator="$2" value="$3" version

    version=$($prog --version | awk '{print $NF; exit}')

    awk -vv1="$version" -vv2="$value" 'BEGIN {
        split(v1, a, /\./); split(v2, b, /\./);
        if (a[1] == b[1]) {
            exit (a[2] '$operator' b[2]) ? 0 : 1
        }
        else {
            exit (a[1] '$operator' b[1]) ? 0 : 1
        }
    }'
}

if toolversion grep '>=' 2.6; then
   # do something awesome
fi
is_first_floating_number_bigger () {
    number1="$1"
    number2="$2"

    [ ${number1%.*} -eq ${number2%.*} ] && [ ${number1#*.} \> ${number2#*.} ] || [ ${number1%.*} -gt ${number2%.*} ];
    result=$?
    if [ "$result" -eq 0 ]; then result=1; else result=0; fi

    __FUNCTION_RETURN="${result}"
}
numCompare(){

awk-v n1=“$1”-v n2=“$2”开始{printf”%s”(n1使用korn shell,在bash中可能需要分别比较小数部分

#!/bin/ksh
X=0.2
Y=0.2
echo $X
echo $Y

if [[ $X -lt $Y ]]
then
     echo "X is less than Y"
elif [[ $X -gt $Y ]]
then
     echo "X is greater than Y"
elif [[ $X -eq $Y ]]
then
     echo "X is equal to Y"
fi

用于比较无指数表示法、前导或尾随零的浮点的纯bash解决方案:

if [ ${FOO%.*} -eq ${BAR%.*} ] && [ ${FOO#*.} \> ${BAR#*.} ] || [ ${FOO%.*} -gt ${BAR%.*} ]; then
  echo "${FOO} > ${BAR}";
else
  echo "${FOO} <= ${BAR}";
fi
如果[${FOO%.*}-eq${BAR%.*}]&&[${FOO%.*.}\>${BAR%.*.}].[124;${FOO%.*.}-gt${BAR%.*.}],那么
回声“${FOO}>${BAR}”;
其他的

echo“${FOO}当我检查安装的
grails
版本是否大于所需的最低版本时,此脚本可能会有所帮助。希望有帮助

#!/bin/bash                                                                                         

min=1.4                                                                                             
current=`echo $(grails --version | head -n 2 | awk '{print $NF}' | cut -c 1-3)`                         

if [ 1 -eq `echo "${current} < ${min}" | bc` ]                                                          
then                                                                                                
    echo "yo, you have older version of grails."                                                   
else                                                                                                                                                                                                                       
    echo "Hurray, you have the latest version" 
fi
!/bin/bash
最小值=1.4
current=`echo$(grails--version | head-n2 | awk'{print$NF}'| cut-c1-3)`
如果[1-eq`echo“${current}<${min}”|bc`]
然后
echo“哟,你有旧版本的grails。”
其他的
echo“万岁,你有最新版本”
fi

在比较软件包版本的数字时要小心,比如检查grep2.20是否大于2.6版:

$ awk 'BEGIN { print (2.20 >= 2.6) ? "YES" : "NO" }'
NO

$ awk 'BEGIN { print (2.2 >= 2.6) ? "YES" : "NO" }'
NO

$ awk 'BEGIN { print (2.60 == 2.6) ? "YES" : "NO" }'
YES
我用这样的shell/awk函数解决了这样的问题:

numCompare() {
   awk -v n1="$1" -v n2="$2" 'BEGIN {printf "%s " (n1<n2?"<":">=") " %s\n", n1, n2}'
}
# get version of GNU tool
toolversion() {
    local prog="$1" operator="$2" value="$3" version

    version=$($prog --version | awk '{print $NF; exit}')

    awk -vv1="$version" -vv2="$value" 'BEGIN {
        split(v1, a, /\./); split(v2, b, /\./);
        if (a[1] == b[1]) {
            exit (a[2] '$operator' b[2]) ? 0 : 1
        }
        else {
            exit (a[1] '$operator' b[1]) ? 0 : 1
        }
    }'
}

if toolversion grep '>=' 2.6; then
   # do something awesome
fi
is_first_floating_number_bigger () {
    number1="$1"
    number2="$2"

    [ ${number1%.*} -eq ${number2%.*} ] && [ ${number1#*.} \> ${number2#*.} ] || [ ${number1%.*} -gt ${number2%.*} ];
    result=$?
    if [ "$result" -eq 0 ]; then result=1; else result=0; fi

    __FUNCTION_RETURN="${result}"
}
更方便 使用Bash的数字上下文可以更方便地执行此操作:

if (( $(echo "$num1 > $num2" |bc -l) )); then
  …
fi
解释 管道通过基本计算器命令
bc
返回1或0

选项
-l
相当于
--mathlib
;它加载标准数学库

将整个表达式括在双括号
(())
之间将分别将这些值转换为true或false

请确保安装了
bc
基本计算器软件包。


这同样适用于科学格式的浮点数,只要使用大写字母
E
,例如
num1=3.44E6

我使用此处的答案并将其放入函数中,您可以这样使用:

is_first_floating_number_bigger 1.5 1.2
result="${__FUNCTION_RETURN}"
. /path/to/the/new-file.sh
一旦调用,
echo$result
在这种情况下将为
1
,否则为
0

职能:

numCompare() {
   awk -v n1="$1" -v n2="$2" 'BEGIN {printf "%s " (n1<n2?"<":">=") " %s\n", n1, n2}'
}
# get version of GNU tool
toolversion() {
    local prog="$1" operator="$2" value="$3" version

    version=$($prog --version | awk '{print $NF; exit}')

    awk -vv1="$version" -vv2="$value" 'BEGIN {
        split(v1, a, /\./); split(v2, b, /\./);
        if (a[1] == b[1]) {
            exit (a[2] '$operator' b[2]) ? 0 : 1
        }
        else {
            exit (a[1] '$operator' b[1]) ? 0 : 1
        }
    }'
}

if toolversion grep '>=' 2.6; then
   # do something awesome
fi
is_first_floating_number_bigger () {
    number1="$1"
    number2="$2"

    [ ${number1%.*} -eq ${number2%.*} ] && [ ${number1#*.} \> ${number2#*.} ] || [ ${number1%.*} -gt ${number2%.*} ];
    result=$?
    if [ "$result" -eq 0 ]; then result=1; else result=0; fi

    __FUNCTION_RETURN="${result}"
}
或具有调试输出的版本:

is_first_floating_number_bigger () {
    number1="$1"
    number2="$2"

    echo "... is_first_floating_number_bigger: comparing ${number1} with ${number2} (to check if the first one is bigger)"

    [ ${number1%.*} -eq ${number2%.*} ] && [ ${number1#*.} \> ${number2#*.} ] || [ ${number1%.*} -gt ${number2%.*} ];
    result=$?
    if [ "$result" -eq 0 ]; then result=1; else result=0; fi

    echo "... is_first_floating_number_bigger: result is: ${result}"

    if [ "$result" -eq 0 ]; then
        echo "... is_first_floating_number_bigger: ${number1} is not bigger than ${number2}"
    else
        echo "... is_first_floating_number_bigger: ${number1} is bigger than ${number2}"
    fi

    __FUNCTION_RETURN="${result}"
}
只需将函数保存在一个单独的
.sh
文件中,并按如下方式包含它:

is_first_floating_number_bigger 1.5 1.2
result="${__FUNCTION_RETURN}"
. /path/to/the/new-file.sh
这个怎么样

VAL_TO_CHECK="1.00001"
if [ $(awk '{printf($1 >= $2) ? 1 : 0}' <<<" $VAL_TO_CHECK 1 ") -eq 1 ] ; then
    echo "$VAL_TO_CHECK >= 1"
else
    echo "$VAL_TO_CHECK < 1"
fi
VAL_TO_CHECK=“1.00001”

如果[$(awk'{printf($1>=$2)?1:0}
awk
和类似的工具(我盯着你看
sed
…)应该被扔进旧项目的垃圾箱,所有人都不敢碰这些代码,因为它们是用从不读的语言编写的

或者你是一个相对罕见的需要优先考虑CPU使用优化而不是代码维护优化的项目……在这种情况下,继续吧

如果不是,为什么不使用可读的、明确的东西,比如
python
?你的同事和未来的自己会感谢你。你可以像其他人一样使用
python
与bash内联

num1=3.17648E-22
num2=1.5
if python -c "exit(0 if $num1 < $num2 else 1)"; then
    echo "yes, $num1 < $num2"
else
    echo "no, $num1 >= $num2"
fi
num1=3.17648E-22
num2=1.5
如果python-c“exit(如果$num1<$num2否则为1,则为0)”,则
回应“是,$num1<$num2”
其他的
echo“否,$num1>=$num2”
fi

如果出现以下情况,您可以将
awk
与bash结合使用:

if awk "BEGIN {exit !($d1 >= $d2)}"; then
    echo "yes"
else 
    echo "no"
fi

当然,如果您不需要真正的浮点运算,只需对始终只有两个十进制数字的美元值进行运算,您可以删除点(实际上是乘以100)并比较结果整数

if [[ $((10#${num1/.})) < $((10#${num2/.})) ]]; then
    ...
如果[$((10#${num1/}))<$((10#${num2/}))];那么
...
这显然要求您确保两个值的小数位数相同。

使用bashj(),一种支持java的bash变体,您只需编写(并且易于阅读):

!/usr/bin/bashj
#!java

静态int doubleCompare(双a,双b){return((a>b)?1:(aa解决方案支持所有可能的符号,包括带有大写和小写指数的科学符号(例如,
12.00e4
):


如果($(bc-l请检查以下编辑的代码:-

#!/bin/bash

export num1=(3.17648*e-22)
export num2=1.5

st=$((`echo "$num1 < $num2"| bc`))
if [ $st -eq 1 ]
  then
    echo -e "$num1 < $num2"
  else
    echo -e "$num1 >= $num2"
fi
!/bin/bash
出口num1=(3.17648*e-22)
出口num2=1.5
st=$(`echo“$num1<$num2”| bc`)
如果[$st-等式1]
然后
echo-e“$num1<$num2”
其他的
echo-e“$num1>=$num2”
fi

这很有效。

当它作为这个问题的一个dup关闭时,我将此作为一个答案发布,因此它也适用于这里:

为了简单明了,只需使用awk进行计算,因为它是一个标准的UNIX工具,因此很可能与bc一样存在,并且在语法上更易于使用

关于这个问题:

$ cat tst.sh
#!/bin/bash

num1=3.17648e-22
num2=1.5

awk -v num1="$num1" -v num2="$num2" '
BEGIN {
    print "num1", (num1 < num2 ? "<" : ">="), "num2"
}
'

$ ./tst.sh
num1 < num2

只需用printf替换
echo
(它理解浮动):

st=$(printf'%50G<%50G\n'$num1'$num2'| bc-l)
对于“e-format”,我指的是与指数表示法(也称为科学表示法)相关的:是的,但要解决问题