我正在努力比较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

不幸的是,我有一些问题与num1的正确处理可以是“电子格式”。


当前回答

一个非常简单的perl解决方案:

$ num1=3.2E8
$ num2=2.5E9
$ perl -e "print $num2 > $num1? \"true\" : \"false\", \"\n\";"
true
$ perl -e "print $num2 < $num1? \"true\" : \"false\", \"\n\";"
false

这证明perl真正理解科学数字表示的“E”符号:

$ perl -e "print $num1, \"\n\";"
320000000

如果你在shell脚本中需要一个' If '语句,在perl中使用exit命令:

$ if perl -e "exit ($num1 > $num2? 0 : 1);"; then echo true; else echo false; fi
false

注意,在shell脚本中,返回0的命令表示成功,并传递'if'条件(因此if-子句被执行)。任何其他非零返回值都意味着失败。

其他回答

这个脚本可以帮助我检查安装的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 an older version of Grails."
else
    echo "Hurray, you have the latest version"
fi

更加方便

这可以使用Bash的数值上下文更方便地完成:

if (( $(echo "$num1 > $num2" |bc -l) )); then
  …
fi

解释

通过基本计算器命令bc的管道将返回1或0。

选项-l等价于——mathlib;它加载标准数学库。

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

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

注意:指数符号应该写成*10^;不是E,也不是E。

例如:

$ echo "1*10^3==1000" |bc
1

$ echo "1E3==1000" |bc
0

这里讨论了克服这种bc限制的策略。

有一种简单的方法,比AWK快一点,而且不需要安装bc。它利用sort对浮点数进行排序的能力:

A=1280.4
B=9.325
LOW=$(sort -n <<< "$A"$'\n'"$B" | head -1)
if [[ "$LOW" == "$A" ]]; then
    echo "A <= B"
else
    echo "A >= B"
fi

当然,对于相等的数字,这是行不通的。

当然,如果你不需要真正的浮点运算,只需要对例如美元值进行运算,其中总是有两个十进制数字,你可能只需要去掉点(有效地乘以100)并比较得到的整数。

if [[ $((10#${num1/.})) < $((10#${num2/.})) ]]; then
    ...

这显然需要确保两个值的小数点后数位相同。

使用bashj,一个支持Java的Bash变种,你只需要写(而且很容易读):

#!/usr/bin/bashj

#!java
static int doubleCompare(double a,double b) {return((a>b) ? 1 : (a<b) ? -1 : 0);}

#!bashj
num1=3.17648e-22
num2=1.5
comp=j.doubleCompare($num1,$num2)
if [ $comp == 0 ] ; then echo "Equal" ; fi
if [ $comp == 1 ] ; then echo "$num1 > $num2" ; fi
if [ $comp == -1 ] ; then echo "$num2 > $num1" ; fi

当然,bashj Bash/Java混合提供了更多…