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

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

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

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

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

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


当前回答

在浮点数出现之前,固定小数逻辑是被使用的:

IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33

最后一行是bashim,如果不使用bash,试试下面的代码:

IMG_WIDTH=100
IMG2_WIDTH=3
INTEGER=$(($IMG_WIDTH/$IMG2_WIDTH))
DECIMAL=$(tail -c 3 <<< $((${IMG_WIDTH}00/$IMG2_WIDTH)))
RESULT=$INTEGER.$DECIMAL
echo $RESULT
33.33

代码背后的基本原理是:在除之前乘以100得到两个小数。

其他回答

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

echo "2.1+3.1" |  awk -F "+" '{print ($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))

你可以这样做:

bc <<< 'scale=2; 100/3'
33.33

更新20130926:你可以使用:

bc -l <<< '100/3' # saves a few hits
33.33333333333333333333

bash

正如其他人指出的那样,bash不支持浮点运算,尽管您可以使用一些固定的小数技巧来伪造它,例如使用两个小数:

echo $(( 100 * 1 / 3 )) | sed -e 's/..$/.&/;t' -e 's/.$/.0&/'

输出:

.33

请参阅Nilfred的回答,了解类似但更简洁的方法。

选择

除了提到的bc和awk的替代品,还有以下:

clisp

clisp -x '(/ 1.0 3)'

清理输出:

clisp --quiet -x '(/ 1.0 3)'

或者通过stdin:

echo '(/ 1.0 3)' | clisp --quiet | tail -n1

dc

echo 2k 1 3 /p | dc

天才cli计算器

echo 1/3.0 | genius

ghostscript

echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p' 

gnuplot

echo 'pr 1/3.' | gnuplot

Imagemagick

convert xc: -format '%[fx:1/3]' info:

或者通过stdin:

echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }

jq

jq -n 1/3

或者通过stdin:

echo 1/3 | jq -nf /dev/stdin

ksh

echo 'print $(( 1/3. ))' | ksh

lua

lua -e 'print(1/3)'

或者通过stdin:

echo 'print(1/3)' | lua

maxima

echo '1/3,numer;' | maxima

清理输出:

echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'

node

echo 1/3 | node -p

倍频程

echo 1/3 | octave

perl

echo print 1/3 | perl

python2

echo print 1/3. | python2

python3

echo 'print(1/3)' | python3

R

echo 1/3 | R --no-save

清理输出:

echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'

ruby

echo puts 1/3.0 | ruby

单位

units 1/3

输出紧凑:

units --com 1/3

水垢

echo 1/3 | wcalc

清理输出:

echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2

zsh

print $(( 1/3. ))

或者通过stdin:

echo 'print $(( 1/3. ))' | zsh

其他来源

Stéphane Chazelas在UL上回答了类似的问题。

您需要多精确的输出?如果你的用例已经可以接受通过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开销。