Jon*_*nas 125 floating-point bash comparison numbers
我正在努力比较bash脚本中的两个浮点数.我有变量,例如
let num1=3.17648e-22
let num2=1.5
Run Code Online (Sandbox Code Playgroud)
现在,我只想对这两个数字进行简单的比较:
st=`echo "$num1 < $num2" | bc`
if [ $st -eq 1]; then
echo -e "$num1 < $num2"
else
echo -e "$num1 >= $num2"
fi
Run Code Online (Sandbox Code Playgroud)
不幸的是,我对num1的正确处理存在一些问题,这可能是"电子格式".:(
任何帮助,欢迎提示!
Ser*_*ndt 139
使用Bash的数字上下文可以更方便地完成此操作:
if (( $(echo "$num1 > $num2" |bc -l) )); then
…
fi
Run Code Online (Sandbox Code Playgroud)
通过基本计算器命令管道bc
返回1或0.
该选项-l
相当于--mathlib
; 它加载标准的数学库.
在双括号之间包含整个表达式(( ))
将这些值分别转换为true或false.
请确保bc
安装了基本的计算器包.
alr*_*sdi 97
bash只处理整数数学但你可以使用bc
如下命令:
$ num1=3.17648E-22
$ num2=1.5
$ echo $num1'>'$num2 | bc -l
0
$ echo $num2'>'$num1 | bc -l
1
Run Code Online (Sandbox Code Playgroud)
请注意,指数符号必须为大写
anu*_*ava 24
最好awk
用于非整数数学.您可以使用此bash实用程序功能:
numCompare() {
awk -v n1="$1" -v n2="$2" 'BEGIN {printf "%s " (n1<n2?"<":">=") " %s\n", n1, n2}'
}
Run Code Online (Sandbox Code Playgroud)
称之为:
numCompare 5.65 3.14e-22
5.65 >= 3.14e-22
numCompare 5.65e-23 3.14e-22
5.65e-23 < 3.14e-22
numCompare 3.145678 3.145679
3.145678 < 3.145679
Run Code Online (Sandbox Code Playgroud)
use*_*ser 21
用于比较不带指数表示法,前导或尾随零的浮点数的纯bash解决方案:
if [ ${FOO%.*} -eq ${BAR%.*} ] && [ ${FOO#*.} \> ${BAR#*.} ] || [ ${FOO%.*} -gt ${BAR%.*} ]; then
echo "${FOO} > ${BAR}";
else
echo "${FOO} <= ${BAR}";
fi
Run Code Online (Sandbox Code Playgroud)
逻辑运算符的顺序很重要.将整数部分作为数字进行比较,将小数部分有意地作为字符串进行比较.使用此方法将变量拆分为整数和小数部分.
不会将浮点数与整数(没有点)进行比较.
ung*_*rys 14
你可以使用awk结合bash if条件,awk将打印1或0,这些将由if子句用true或false解释.
if (( $(awk 'BEGIN {print ("'$d1'" >= "'$d2'")}') )); then
echo "yes"
else
echo "no"
fi
Run Code Online (Sandbox Code Playgroud)
支持所有可能的符号的解决方案,包括具有大写和小写指数的科学符号(例如,12.00e4
):
if (( $(bc -l <<< "${value1/e/E} < ${value2/e/E}") ))
then
echo "$value1 is smaller than $value2"
fi
Run Code Online (Sandbox Code Playgroud)
在比较包版本的数字时要小心,比如检查grep 2.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
Run Code Online (Sandbox Code Playgroud)
我用这样的shell/awk函数解决了这个问题:
# 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
Run Code Online (Sandbox Code Playgroud)
请检查以下编辑后的代码:
#!/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
Run Code Online (Sandbox Code Playgroud)
这效果很好。
AWK和类似的工具(我正盯着你看sed
……)应该被扔进旧项目的垃圾箱,其中的代码每个人都不敢碰,因为它是用一种从不读的语言编写的。
或者您是一个相对罕见的项目,需要优先考虑 CPU 使用优化而不是代码维护优化......在这种情况下,请继续。
如果不是,那么,只需使用可读且明确的东西,例如 Python。你的同事和未来的自己都会感谢你。您可以像其他所有代码一样使用与 Bash 内联的 Python 代码。
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
Run Code Online (Sandbox Code Playgroud)
当然,如果您不需要真正的浮点算术,只需对例如总是有两个十进制数字的美元值进行算术,您就可以删除点(有效乘以100)并比较所得的整数。
if [[ $((10#${num1/.})) < $((10#${num2/.})) ]]; then
...
Run Code Online (Sandbox Code Playgroud)
显然,这要求您确保两个值的小数位数相同。
归档时间: |
|
查看次数: |
152792 次 |
最近记录: |