Answers:
您可以分别检查整数和小数部分:
#!/bin/bash
min=12.45
val=12.35
if (( ${val%%.*} < ${min%%.*} || ( ${val%%.*} == ${min%%.*} && ${val##*.} < ${min##*.} ) )) ; then
min=$val
fi
echo $min
正如Fered在评论中所说,只有两个数字都具有小数部分且两个小数部分具有相同的数字时,该方法才有效。这是一个适用于整数或小数以及任何bash运算符的版本:
#!/bin/bash
shopt -s extglob
fcomp() {
local oldIFS="$IFS" op=$2 x y digitx digity
IFS='.' x=( ${1##+([0]|[-]|[+])}) y=( ${3##+([0]|[-]|[+])}) IFS="$oldIFS"
while [[ "${x[1]}${y[1]}" =~ [^0] ]]; do
digitx=${x[1]:0:1} digity=${y[1]:0:1}
(( x[0] = x[0] * 10 + ${digitx:-0} , y[0] = y[0] * 10 + ${digity:-0} ))
x[1]=${x[1]:1} y[1]=${y[1]:1}
done
[[ ${1:0:1} == '-' ]] && (( x[0] *= -1 ))
[[ ${3:0:1} == '-' ]] && (( y[0] *= -1 ))
(( ${x:-0} $op ${y:-0} ))
}
for op in '==' '!=' '>' '<' '<=' '>='; do
fcomp $1 $op $2 && echo "$1 $op $2"
done
1.00000000000000000000000001
大于2
。
Bash不了解浮点运算。它将包含小数点的数字视为字符串。
请改用awk或bc。
#!/bin/bash
min=12.45
val=10.35
if [ 1 -eq "$(echo "${val} < ${min}" | bc)" ]
then
min=${val}
fi
echo "$min"
如果您打算进行大量数学运算,则最好依赖python或perl。
您可以使用num-utils软件包 进行简单的操作...
有关更严格的数学知识,请参见此链接...。它描述了几个选项,例如。
一个例子 numprocess
echo "123.456" | numprocess /+33.267,%2.33777/
# 67.0395291239087
A programs for dealing with numbers from the command line
The 'num-utils' are a set of programs for dealing with numbers from the
Unix command line. Much like the other Unix command line utilities like
grep, awk, sort, cut, etc. these utilities work on data from both
standard in and data from files.
Includes these programs:
* numaverage: A program for calculating the average of numbers.
* numbound: Finds the boundary numbers (min and max) of input.
* numinterval: Shows the numeric intervals between each number in a sequence.
* numnormalize: Normalizes a set of numbers between 0 and 1 by default.
* numgrep: Like normal grep, but for sets of numbers.
* numprocess: Do mathematical operations on numbers.
* numsum: Add up all the numbers.
* numrandom: Generate a random number from a given expression.
* numrange: Generate a set of numbers in a range expression.
* numround: Round each number according to its value.
这是一个bash
hack ...它将整数前导0加到整数中,使字符串从左到右的比较有意义。此段特定代码要求 min和val实际上都具有一个小数点和至少一个十进制数字。
min=12.45
val=10.35
MIN=0; VAL=1 # named array indexes, for clarity
IFS=.; tmp=($min $val); unset IFS
tmp=($(printf -- "%09d.%s\n" ${tmp[@]}))
[[ ${tmp[VAL]} < ${tmp[MIN]} ]] && min=$val
echo min=$min
输出:
min=10.35
对于浮点数的简单计算(+-* /和比较),可以使用awk。
min=$(echo 12.45 10.35 | awk '{if ($1 < $2) print $1; else print $2}')
或者,如果您具有ksh93或zsh(而非bash),则可以使用Shell的内置算术,该算术支持浮点数。
if ((min>val)); then ((val=min)); fi
有关更高级的浮点计算,请查找bc。它实际上适用于任意精度的定点数。
该命令sort
具有一个选项-g
(--general-numeric-sort
),可通过查找最小值或最大值来比较<
“小于”或>
“大于”。
这些示例正在寻找最低要求:
$ printf '12.45\n10.35\n' | sort -g | head -1
10.35
它可以与浮点数的相当通用的符号一起使用,例如E符号
$ printf '12.45E-10\n10.35\n' | sort -g | head -1
12.45E-10
注意E-10
,使第一个数字0.000000001245
确实小于10.35
。
浮点标准IEEE754定义了一些特殊值。对于这些比较,有趣的是INF
无穷大。还有负无穷大。两者都是标准中定义明确的值。
$ printf 'INF\n10.35\n' | sort -g | head -1
10.35
$ printf '-INF\n10.35\n' | sort -g | head -1
-INF
要找到最大用途sort -gr
而不是sort -g
,请颠倒排序顺序:
$ printf '12.45\n10.35\n' | sort -gr | head -1
12.45
要实现<
(“小于”)比较,以便可以在if
等中使用,请将最小值与值之一进行比较。如果最小值等于该值,则与text相比,它小于另一个值:
$ a=12.45; b=10.35
$ [ "$a" = "$(printf "$a\n$b\n" | sort -g | head -1)" ]
$ echo $?
1
$ a=12.45; b=100.35
$ [ "$a" = "$(printf "$a\n$b\n" | sort -g | head -1)" ]
$ echo $?
0
a == min(a, b)
与a <= b
。值得一提的是,检查的严格程度并不低于。如果你想做到这一点,你需要检查a == min(a, b) && a != max(a, b)
,。换句话说a <= b and not a >= b
只需使用ksh
(ksh93
精确地)或zsh
,它们本身就支持浮点运算:
$ cat test.ksh
#!/bin/ksh
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo "$min"
$ ./test.ksh
10.35
编辑:对不起,我ksh93
已经错过了建议。保持我的回答只是为了清楚地说明在开头问题中发布的脚本,可以在shell开关外部使用而无需进行任何更改。
Edit2:请注意,ksh93
要求变量内容与您的语言环境一致,即与法国语言环境一致,必须使用逗号而不是点:
...
min=12,45
val=10,35
...
一个更可靠的解决方案是在脚本的开头设置语言环境,以确保无论用户的语言环境如何,该语言环境都可以工作:
...
export LC_ALL=C
min=12.45
val=10.35
...
.
(因此,在小数点分隔符所在的世界的一半中无效,
)。zsh
没有那个问题。
LC_ALL
,这也意味着数字将不会以用户首选的格式显示(或输入)。请参阅unix.stackexchange.com/questions/87745/what-does-lc-all-c-do/…,以获得可能更好的方法。
.
。
min=$(echo "${min}sa ${val}d la <a p" | dc)
使用该dc
计算器,以s
撕开值$min
寄存器a
和d
uplicates的值$val
到它的主执行堆栈的顶部。然后,它将l
内容a
放到栈顶,此时看起来像:
${min} ${val} ${val}
在<
弹出顶部的两个条目从堆栈中并对它们进行比较。因此堆栈如下所示:
${val}
如果最上面的条目少于第二个,它将把内容推a
到最上面,因此堆栈看起来像:
${min} ${val}
否则它什么也不做,堆栈看起来仍然像这样:
${val}
然后,它仅p
清除顶部堆栈条目。
因此,对于您的问题:
min=12.45
val=12.35
echo "${min}sa ${val}d la <a p" | dc
###OUTPUT
12.35
但:
min=12.45
val=12.55
echo "${min}sa ${val}d la <a p" | dc
###OUTPUT
12.45
为什么不使用旧的,好expr
?
语法示例:
if expr 1.09 '>' 1.1 1>/dev/null; then
echo 'not greater'
fi
对于真表达式,expr退出代码为0,并将字符串“ 1”发送到stdout。反转为错误的表达式。
我已经使用GNU和FreeBSD 8 expr对此进行了检查。
expr 1.09 '<' -1.1
将打印1
并以0
(成功)退出。
要检查两个(可能是小数)数字是否顺序正确sort
(可移植):
min=12.45
val=12.55
if { echo $min ; echo $val ; } | sort -n -c 2>/dev/null
then
echo min is smallest
else
echo val is smallest
fi
但是,如果您实际上想保持最小值更新,则不需要if
。对数字进行排序,并始终使用第一个(最小)一个:
min=12.45
val=12.55
smallest=$({ echo $min ; echo $val ; } | sort -n | head -n 1)
echo $smallest
min=$smallest
通常我用嵌入式python代码做类似的事情:
#!/bin/sh
min=12.45
val=10.35
python - $min $val<<EOF
if ($min > $val):
print $min
else:
print $val
EOF
0.5
和0.06
)就无法解决此问题。您最好使用已经理解十进制表示法的工具。