RIc*_*ams 33 shell shell-script arithmetic
我想在 shell 脚本中比较两个浮点数。以下代码不起作用:
#!/bin/bash
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo $min
Run Code Online (Sandbox Code Playgroud)
Dan*_*und 44
Bash 不了解浮点运算。它将包含小数点的数字视为字符串。
请改用 awk 或 bc。
#!/bin/bash
min=12.45
val=10.35
if [ 1 -eq "$(echo "${val} < ${min}" | bc)" ]
then
min=${val}
fi
echo "$min"
Run Code Online (Sandbox Code Playgroud)
如果您打算进行大量数学运算,最好依靠 python 或 perl。
Pet*_*r.O 12
您可以使用包num-utils 进行简单的操作...
对于更严肃的数学,请参阅此链接...它描述了几个选项,例如。
一个例子 numprocess
echo "123.456" | numprocess /+33.267,%2.33777/
# 67.0395291239087
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
这是一个bash
黑客......它在整数中添加前导 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
Run Code Online (Sandbox Code Playgroud)
输出:
min=10.35
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 12
对于浮点数(+-*/ 和比较)的简单计算,您可以使用 awk。
min=$(echo 12.45 10.35 | awk '{if ($1 < $2) print $1; else print $2}')
Run Code Online (Sandbox Code Playgroud)
或者,如果您有 ksh93 或 zsh(不是 bash),则可以使用支持浮点数的 shell 内置算法。
if ((min>val)); then ((val=min)); fi
Run Code Online (Sandbox Code Playgroud)
有关更高级的浮点计算,请查找bc。它实际上适用于任意精度的固定点数。
ata*_*ata 10
您可以分别检查整数和小数部分:
#!/bin/bash
min=12.45
val=12.35
if (( ${val%%.*} < ${min%%.*} || ( ${val%%.*} == ${min%%.*} && ${val##*.} < ${min##*.} ) )) ; then
min=$val
fi
echo $min
Run Code Online (Sandbox Code Playgroud)
正如 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
Run Code Online (Sandbox Code Playgroud)
该命令sort
有一个选项-g
( --general-numeric-sort
),可用于通过查找最小值或最大值来比较<
“小于”或>
“大于”。
这些示例正在寻找最小值:
$ printf '12.45\n10.35\n' | sort -g | head -1
10.35
Run Code Online (Sandbox Code Playgroud)
它适用于非常通用的浮点数表示法,例如 E-Notation
$ printf '12.45E-10\n10.35\n' | sort -g | head -1
12.45E-10
Run Code Online (Sandbox Code Playgroud)
注意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
Run Code Online (Sandbox Code Playgroud)
要找到最大使用sort -gr
而不是sort -g
,颠倒排序顺序:
$ printf '12.45\n10.35\n' | sort -gr | head -1
12.45
Run Code Online (Sandbox Code Playgroud)
要实现<
(“小于”)比较,以便可以在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
Run Code Online (Sandbox Code Playgroud)