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

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

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

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

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

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


当前回答

正如其他人指出的那样,bash没有内置的浮点运算符。

您可以在bash中实现浮点数,甚至不使用bc和awk之类的计算器程序,或者任何与此相关的外部程序。

我在我的项目shellmath中正是这样做的,分三个基本步骤:

把数字分成整数部分和小数部分 使用内置的整数运算符分别处理各个部分,同时注意位值和进位 重新组合结果

作为一个挑逗,我添加了一个演示脚本,使用以x=0为中心的泰勒级数计算e。

如果您有时间,请查看一下。欢迎您的反馈!

其他回答

There are scenarios in wich you cannot use bc becouse it might simply not be present, like in some cut down versions of busybox or embedded systems. In any case limiting outer dependencies is always a good thing to do so you can always add zeroes to the number being divided by (numerator), that is the same as multiplying by a power of 10 (you should choose a power of 10 according to the precision you need), that will make the division output an integer number. Once you have that integer treat it as a string and position the decimal point (moving it from right to left) a number of times equal to the power of ten you multiplied the numerator by. This is a simple way of obtaining float results by using only integer numbers.

您需要多精确的输出?如果你的用例已经可以接受通过bin的近似值,你甚至可以更进一步,利用POSIX退出码[0:256)(所有其他整数修改回该范围)。

在gawk/nawk/mawk-1中,它已经给了我epoch秒到整数级别,但我想扩展它以提取近毫秒的精度,但不是过分迂迂的,我在POSIX shell中运行这个命令

exit $(( 10#` gdate +%5N ` * 256 / 100000 ))

直接分配一个表示0的5位整数。将gnu-date的XXXXXX输出到256个bin中的1个,然后在awk获得system()调用的退出码(即所选的bin #)后撤销这256个bin。我发现这种方法比使用完整的getline调用开销更低。

该方法还直接将输出捕获到POSIX退出码中,而不是打印出一个额外的终端。

(如果以这种方式编写,shell算术自动将其转换为整数而不是* 0.0256)。把它们放在awk函数中,就像这样。10#强制以10为基数,以防止posix shell将“01733”解释为八进制数。

function msecs() {     # n x 2**-8 = n divided by 256

    return 2^-8 * \
           system( "exit \44\50\50 "      \
                   " 10\43\140 gdate \53"  \
                   "%5N\140 \52 " \
                   "256 \57 100000 \51\51" )
}

对于我自己的代码,我应用了另外0.6%的理发来考虑shell开销。

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

这里我将一些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没有内置的浮点运算符。

您可以在bash中实现浮点数,甚至不使用bc和awk之类的计算器程序,或者任何与此相关的外部程序。

我在我的项目shellmath中正是这样做的,分三个基本步骤:

把数字分成整数部分和小数部分 使用内置的整数运算符分别处理各个部分,同时注意位值和进位 重新组合结果

作为一个挑逗,我添加了一个演示脚本,使用以x=0为中心的泰勒级数计算e。

如果您有时间,请查看一下。欢迎您的反馈!

我知道很老了,但太诱人了。所以,答案是:你不能……但你可以。让我们试试这个:

$IMG_WIDTH=1024
$IMG2_WIDTH=2048

$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"

这样,在纯bash(不需要启动其他进程)中,在该点之后得到2位截断的数字(称为舍入到下位)。当然,如果你只需要这一点后面的一位数,你可以乘以10,然后对10取模。

它的作用:

First $((…))执行整数除法; 第二个$((…))对一个大100倍的数进行整数除法,本质上是将2位数字移到点的左边,然后(%)通过做模只得到这2位数字。

奖励轨道:bc版本× 1000在我的笔记本电脑上花了1.8秒,而纯bash版本花了0.016秒。