我试图在Bash脚本中划分两个图像宽度,但Bash给我0作为结果:

RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))

我确实研究了Bash指南,我知道我应该使用bc,在互联网上的所有例子中,他们都使用bc。在echo中,我试图把同样的东西放在我的SCALE中,但它不起作用。

以下是我在教程中找到的例子:

echo "scale=2; ${userinput}" | bc 

我怎么能让巴斯给我0.5这样的浮点数呢?


当前回答

如果你找到了你喜欢的变体,你也可以把它包装到一个函数中。

这里我将一些bashism包装到div函数中:

一个衬套:

function div { local _d=${3:-2}; local _n=0000000000; _n=${_n:0:$_d}; local _r=$(($1$_n/$2)); _r=${_r:0:-$_d}.${_r: -$_d}; echo $_r;}

或多行:

function div {
  local _d=${3:-2}
  local _n=0000000000
  _n=${_n:0:$_d}
  local _r=$(($1$_n/$2))
  _r=${_r:0:-$_d}.${_r: -$_d}
  echo $_r
}

现在你得到了这个函数

div <dividend> <divisor> [<precision=2>]

然后像这样使用它

> div 1 2
.50

> div 273 123 5
2.21951

> x=$(div 22 7)
> echo $x
3.14

更新 我添加了一个小脚本,为您提供了bash的基本浮点数操作:

用法:

> add 1.2 3.45
4.65
> sub 1000 .007
999.993
> mul 1.1 7.07
7.7770
> div 10 3
3.
> div 10 3.000
3.333

这里是脚本:

#!/bin/bash
__op() {
        local z=00000000000000000000000000000000
        local a1=${1%.*}
        local x1=${1//./}
        local n1=$((${#x1}-${#a1}))
        local a2=${2%.*}
        local x2=${2//./}
        local n2=$((${#x2}-${#a2}))
        local n=$n1
        if (($n1 < $n2)); then
                local n=$n2
                x1=$x1${z:0:$(($n2-$n1))}
        fi
        if (($n1 > $n2)); then
                x2=$x2${z:0:$(($n1-$n2))}
        fi
        if [ "$3" == "/" ]; then
                x1=$x1${z:0:$n}
        fi
        local r=$(($x1"$3"$x2))
        local l=$((${#r}-$n))
        if [ "$3" == "*" ]; then
                l=$(($l-$n))
        fi
        echo ${r:0:$l}.${r:$l}
}
add() { __op $1 $2 + ;}
sub() { __op $1 $2 - ;}
mul() { __op $1 $2 "*" ;}
div() { __op $1 $2 / ;}

其他回答

虽然在Bash中不能使用浮点除法,但可以使用定点除法。你所要做的就是把整数乘以10的次方,然后把整数部分除掉,用取模运算得到小数部分。根据需要舍入。

#!/bin/bash

n=$1
d=$2

# because of rounding this should be 10^{i+1}
# where i is the number of decimal digits wanted
i=4
P=$((10**(i+1)))
Pn=$(($P / 10))
# here we 'fix' the decimal place, divide and round tward zero
t=$(($n * $P / $d + ($n < 0 ? -5 : 5)))
# then we print the number by dividing off the interger part and
# using the modulo operator (after removing the rounding digit) to get the factional part.
printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn))

稍微改进一下马文的回答:

RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")

BC并不总是安装包。

让我们举个例子来理解,如果你想找到n个数组元素的平均值(当然平均值将是浮点数/小数)

declare -a arr
echo "How many numbers you want to enter?"
read n
echo "Enter the Array Elements"
for(( i=0 ; i<$n ; i++))
do
      read array_elements
      arr[$i]="$array_elements"
done
sum=0
for i in "${arr[@]}"
do
     #sum and avg
     sum=$(($sum + $i))
     #average will come in decimals
     avg=`echo $sum / $n | bc -l`
done
# Output results:
printf "Average of Array Elements %.2f:" $avg

因此,我们将使用"| bc -l"来进行浮动计算

下面是awk命令:-F =字段分隔符== +

echo "2.1+3.1" |  awk -F "+" '{print ($1+$2)}'

** bash/shell中的注入安全浮点数学

注意:这个回答的重点是为在bash(或其他shell)中执行数学的注入安全解决方案提供思路。当然,同样也可以使用,只需稍作调整即可执行高级字符串处理等。

所提出的大多数解决方案都是使用外部数据(变量、文件、命令行、环境变量)动态构造小脚本。外部输入可用于向引擎中注入恶意代码,其中很多是恶意代码

下面是使用各种语言进行基本数学计算的比较,其中结果为浮点数。它计算A + B * 0.1(作为浮点数)。

所有的解决方案都试图避免创建难以维护的动态脚本,而是使用静态程序,并将参数传递给指定的变量。它们将安全地处理具有特殊字符的参数-减少代码注入的可能性。例外是'BC',它不提供输入/输出功能

例外是'bc',它不提供任何输入/输出,所有数据都来自stdin中的程序,所有输出都到stdout。所有计算都在沙箱中执行,不允许出现副作用(打开文件等)。理论上,注射是安全的设计!

A=5.2
B=4.3

# Awk: Map variable into awk
# Exit 0 (or just exit) for success, non-zero for error.
#
awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'

# Perl
perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"

# Python 2
python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"

# Python 3
python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"

# BC
bc <<< "scale=1 ; $A + $B * 0.1"