我正在努力比较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的正确处理可以是“电子格式”。
我正在努力比较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的正确处理可以是“电子格式”。
当前回答
你可以使用AWK结合Bash if条件:
if awk "BEGIN {exit !($d1 >= $d2)}"; then
echo "yes"
else
echo "no"
fi
其他回答
以下是基于gawk+GMP的方法,用于考虑更广泛的潜在输入:
echo " 5.65e-23 3.14e-22\n
5.65 3.14e-2203\n
3.145678 3.145679\n
3.25353E+9293 325353e9288\n
3.14159e+200000000001 3.1415899999999999999999E200000000001\n
100000 100000.0\n
4096 4096" \
\
| gawk -v PREC=9999999 -nMbe '
NF+=OFS=sprintf(" %s ",
(+($!_=sprintf("%24s",$!_)<+$NF) \
? "<" \
: (+$NF<+$!_) \
? ">" \
: (int(+$!_)==(__=int(+$NF)))*\
(__==+$NF)*index($!_,$NF ) \
? "=" \
: "\342\211\210")' | ecp
5.65e-23 < 3.14e-22
5.65 > 3.14e-2203
3.145678 < 3.145679
3.25353E+9293 ≈ 325353e9288
3.14159e+200000000001 ≈ 3.1415899999999999999999E200000000001
100000 ≈ 100000.0
4096 = 4096
对于更明确的情况,它会给你一个明确的答案
小于<, 大于>,或者 完全等于=(目前是纯整数情况)
当它相对不明确时,它输出Unicode字符U+2248≈ALMOST EQUAL TO,而不是试图不惜一切代价解析它。
大多数情况下你不需要1000万的PREC;像PREC = 32767这样的值对于一个人在典型基础上遇到的大多数情况已经足够好了。
我使用这里的答案,并把它们放在一个函数中。你可以这样使用它:
is_first_floating_number_bigger 1.5 1.2
result="${__FUNCTION_RETURN}"
一旦被调用,echo $result在这种情况下将为1,否则为0。
功能:
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文件中,并像这样包含它:
. /path/to/the/new-file.sh
一个纯Bash解决方案,用于比较没有指数符号,前导或尾随零的浮点数:
if [ ${FOO%.*} -eq ${BAR%.*} ] && [ ${FOO#*.} \> ${BAR#*.} ] || [ ${FOO%.*} -gt ${BAR%.*} ]; then
echo "${FOO} > ${BAR}";
else
echo "${FOO} <= ${BAR}";
fi
逻辑运算符的顺序很重要。整数部分作为数字进行比较,小数部分故意作为字符串进行比较。使用这种方法将变量分成整数部分和小数部分。
它不会比较浮点数和整数(不带点)。
一个非常简单的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-子句被执行)。任何其他非零返回值都意味着失败。
你可以使用AWK结合Bash if条件:
if awk "BEGIN {exit !($d1 >= $d2)}"; then
echo "yes"
else
echo "no"
fi