我正在尝试在Bash脚本中计算两个图像宽度的商,但是Bash给出了0
作为结果:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
我已经学习了Bash指南,知道应该使用bc
。在网上的所有例子中,他们都使用bc
。在echo
中,我尝试将相同的内容放入我的SCALE
中,但它没有起作用。这是我在教程中找到的例子:
echo "scale=2; ${userinput}" | bc
我该如何让Bash输出一个像 0.5
这样的浮点数?
我正在尝试在Bash脚本中计算两个图像宽度的商,但是Bash给出了0
作为结果:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
我已经学习了Bash指南,知道应该使用bc
。在网上的所有例子中,他们都使用bc
。在echo
中,我尝试将相同的内容放入我的SCALE
中,但它没有起作用。echo "scale=2; ${userinput}" | bc
我该如何让Bash输出一个像 0.5
这样的浮点数?
你做不到。Bash只支持整数;你必须委托使用像bc
这样的工具。
VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)
或 VAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")
,而不使用 $(( ))(双括号);$(( )) 会在执行命令之前被 bash 展开。 - Nahuel Fouilleul你可以这样做:
bc <<< 'scale=2; 100/3'
33.33
更新 20130926
:你可以使用:
bc -l <<< '100/3' # saves a few hits
33.33333333333333333333
bc -l <<< 'scale=2; 100/3'
。 - Martiebc <<< 'scale=1; 1*3.00001'
精度是5,原因不明,bc <<< 'scale=1; 1/3.000001'
精度为1。有趣的是,除以1可以解决问题:bc <<< 'scale=1; 1*3.00001/1'
精度为1。 - Greg Bellecho 'scale=2; 100/3' | bc
而不是bc <<< 'scale=2; 100/3'
。 - M Imam Pratama正如其他人所指出的,bash
不支持浮点数运算,尽管您可以使用一些固定的小数位技巧来模拟,例如使用两个小数位:
echo $(( 100 * 1 / 3 )) | sed -e 's/..$/.&/;t' -e 's/.$/.0&/'
输出:
.33
请参考Nilfred的回答,该回答提供了一种类似但更简洁的方法。
除了上述的bc
和awk
方案外,还有以下方案:
clisp -x '(/ 1.0 3)'
使用清理过的输出:
clisp --quiet -x '(/ 1.0 3)'
或通过 stdin
:
echo '(/ 1.0 3)' | clisp --quiet | tail -n1
echo 2k 1 3 /p | dc
echo 1/3.0 | genius
echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p'
echo 'pr 1/3.' | gnuplot
convert xc: -format '%[fx:1/3]' info:
或通过 stdin
:
echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }
jq -n 1/3
或者通过 stdin
:
echo 1/3 | jq -nf /dev/stdin
echo 'print $(( 1/3. ))' | ksh
lua -e 'print(1/3)'
或通过标准输入:
echo 'print(1/3)' | lua
echo '1/3,numer;' | maxima
输出已经清理:
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
echo 1/3 | node -p
echo 1/3 | octave
echo print 1/3 | perl
echo print 1/3. | python2
echo 'print(1/3)' | python3
echo 1/3 | R --no-save
输出已经清理干净:
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
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
print $(( 1/3. ))
或通过 stdin
:
echo 'print $(( 1/3. ))' | zsh
Stéphane Chazelas 在 UL 上回答了一个类似的问题。点击查看。
echo $(( 100*1/50)) | sed 's/..$/.&/'
打印出2
而不是0.02
。 - Socowi稍微改进了marvin的回答:
RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")
bc并不总是作为预装软件包提供。
RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')
- aecolleyRESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "
。将结果保留两位小数。 - jmsterbc
是 POSIX 的一部分,通常预先安装。 - fuz你可以通过加上-l
选项(大写字母L)来使用bc
RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)
echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'
以上中," %.2f "告诉printf函数以小数点后两位返回浮点数。我使用echo将变量作为字段输入,因为awk可以正常处理它们。"$1"和"$2"是指输入到awk的第一个和第二个字段。
您可以使用以下方式将结果存储为其他变量:
RESULT = `echo ...`
在浮点数出现之前,使用的是固定小数位的逻辑:
IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33
最后一行是bash命令,如果没有使用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,以获得2位小数。
IMG2_WIDTH=3000
)并防止出错,在bash中的echo之前添加以下行:[[ ${#RESULT} -lt 2 ]] && RESULT="0$RESULT"
。 - Bryan RoachIMG2_WIDTH=3000
)并防止出错,在echo之前添加以下代码(在bash中):[[ ${#RESULT} -lt 2 ]] && RESULT="0$RESULT"
。 - Bryan Roach现在尝试zsh是完美的时机,它几乎是bash的超集,具有许多额外的不错特性,包括浮点数运算。以下是您在zsh中的示例:
% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875
这篇帖子可能对你有所帮助:bash-是否值得在日常使用中切换到zsh?
与使用bc
命令的 "here strings" (<<<
) 不同,就像最受欢迎的示例之一所做的那样,这是我最喜欢的bc
浮点数示例,直接来自bc
手册的EXAMPLES
部分(请参阅手册页man bc
)。
在我们开始之前,请知道一个关于π的方程式: pi = 4*atan(1)
。下面的a()
是bc
数学函数atan()
。
这是如何将浮点数计算结果存储到bash变量中的方法--在本例中存储到名为pi
的变量中。请注意,scale=10
在此处设置精度为10位小数。此后的任何小数位都会被截断。
pi=$(echo "scale=10; 4*a(1)" | bc -l)
现在,为了让一行代码同时打印出该变量的值,只需将echo
命令作为后续命令添加到末尾,如下所示。请注意,指定了10位小数的截断:
pi=$(echo "scale=10; 4*a(1)" | bc -l); echo $pi
3.1415926532
最后,我们来加入一些四舍五入。这里我们将使用printf
函数将结果保留4位小数。请注意,3.14159...
现在四舍五入为3.1416
。由于我们进行了四舍五入,因此不再需要使用scale=10
来截断到10位小数,因此我们将删除该部分。以下是最终解决方案:
pi=$(printf %.4f $(echo "4*a(1)" | bc -l)); echo $pi
3.1416
(另请参见我在此处的其他答案)。
请注意,dt_min
从 0.01666666666...
被舍入为 0.017
:
start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); echo "dt_sec = $dt_sec; dt_min = $dt_min"
dt_sec = 1; dt_min = 0.017
+
,-
,/
,*
,**
,&
,&&
,<<
等),以及在Bash中进行算术扩展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 / ;}