如何在 bash 中使用浮点除法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12722095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use floating-point division in bash?
提问by Medya Gh
I am trying to divide two image widths in a Bash script, but bash gives me 0
as the result:
我试图在 Bash 脚本中划分两个图像宽度,但结果 bash 给了我0
:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
I did study the Bash guide and I know I should use bc
, in all examples in internet they use bc
. In echo
I tried to put the same thing in my SCALE
but it didn't work.
我确实研究了 Bash 指南,并且我知道我应该bc
在他们使用的 Internet 上的所有示例中使用bc
。在echo
我试图把同样的东西放在我的SCALE
但它没有用。
Here is the example I found in the tutorials:
这是我在教程中找到的示例:
echo "scale=2; ${userinput}" | bc
How can I get Bash to give me a float like 0.5
?
我怎样才能让 Bash 给我一个浮动0.5
?
采纳答案by Ignacio Vazquez-Abrams
You can't. bash onlydoes integers; you mustdelegate to a tool such as bc
.
你不能。bash只处理整数;您必须委托给诸如bc
.
回答by aayoubi
you can do this:
你可以这样做:
bc <<< 'scale=2; 100/3'
33.33
UPDATE20130926
: you can use:
更新20130926
:您可以使用:
bc -l <<< '100/3' # saves a few hits
回答by Thor
bash
猛击
As noted by others, bash
does not support floating point arithmetic, although you could fake it with some fixed decimal trickery, e.g. with two decimals:
正如其他人所指出的,bash
不支持浮点运算,尽管您可以使用一些固定的十进制技巧来伪造它,例如使用两位小数:
echo $(( 100 * 1 / 3 )) | sed 's/..$/.&/'
Output:
输出:
.33
See Nilfred'sanswerfor a similar but more concise approach.
有关类似但更简洁的方法,请参阅Nilfred 的回答。
Alternatives
备择方案
Besides the mentioned bc
and awk
alternatives there are also the following:
除了提到的bc
和awk
替代方案外,还有以下几点:
clisp
夹子
clisp -x '(/ 1.0 3)'
with cleaned up output:
清理输出:
clisp --quiet -x '(/ 1.0 3)'
or through stdin:
或通过标准输入:
echo '(/ 1.0 3)' | clisp --quiet | tail -n1
dc
直流电
echo 2k 1 3 /p | dc
genius cli calculator
天才cli计算器
echo 1/3.0 | genius
ghostscript
鬼稿
echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p'
回声 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p'
gnuplot
图形
echo 'pr 1/3.' | gnuplot
jq
知乎
echo 1/3 | jq -nf /dev/stdin
Or:
或者:
jq -n 1/3
ksh
克什
echo 'print $(( 1/3. ))' | ksh
lua
卢阿
lua -e 'print(1/3)'
or through stdin:
或通过标准输入:
echo 'print(1/3)' | lua
maxima
最大值
echo '1/3,numer;' | maxima
with cleaned up output:
清理输出:
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
node
节点
echo 1/3 | node -p
octave
八度
echo 1/3 | octave
perl
perl
echo print 1/3 | perl
python2
蟒蛇2
echo print 1/3. | python2
python3
蟒蛇3
echo 'print(1/3)' | python3
R
电阻
echo 1/3 | R --no-save
with cleaned up output:
清理输出:
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
ruby
红宝石
echo print 1/3.0 | ruby
wcalc
计算
echo 1/3 | wcalc
With cleaned up output:
使用清理输出:
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
zsh
zsh
echo 'print $(( 1/3. ))' | zsh
units
单位
units 1/3
With compact output:
紧凑的输出:
units --co 1/3
Other sources
其他来源
Stéphane Chazelasanswered a similar questionover on Unix.SX.
回答by adrianlzt
Improving a little the answer of marvin:
稍微改进一下马文的答案:
RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")
bc doesn't come always as installed package.
bc 并不总是作为安装包出现。
回答by user1314742
You could use bc by the -l
option (the L letter)
您可以通过-l
选项(L 字母)使用 bc
RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)
回答by marvin
As an alternative to bc, you can use awk within your script.
作为 bc 的替代方法,您可以在脚本中使用 awk。
For example:
例如:
echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", /}'
In the above, " %.2f " tells the printf function to return a floating point number with two digits after the decimal place. I used echo to pipe in the variables as fields since awk operates properly on them. " $1 " and " $2 " refer to the first and second fields input into awk.
在上面,“ %.2f ”告诉 printf 函数返回一个小数点后两位数的浮点数。我使用 echo 将变量作为字段进行管道传输,因为 awk 可以在它们上正常运行。" $1 " 和 " $2 " 指的是输入到 awk 的第一个和第二个字段。
And you can store the result as some other variable using:
您可以使用以下方法将结果存储为其他变量:
RESULT = `echo ...`
回答by Penghe Geng
It's perfect time to try zsh, an (almost) bash superset, with many additional nice features including floating point math. Here is what your example would be like in zsh:
现在是尝试 zsh 的最佳时机,它是一个(几乎)bash 超集,具有许多额外的不错功能,包括浮点数学。以下是您在 zsh 中的示例:
% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875
This post may help you: bash - Worth switching to zsh for casual use?
这篇文章可能对您有所帮助:bash - 是否值得切换到 zsh 以供随意使用?
回答by Nilfred
Well, before float was a time where fixed decimals logic was used:
好吧,在 float 之前是使用固定小数逻辑的时代:
IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33
Last line is a bashim, if not using bash, try this code instead:
最后一行是 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
The rationale behind the code is: multiply by 100 before divide to get 2 decimals.
代码背后的基本原理是:在除法之前乘以 100 得到 2 位小数。
回答by bebbo
If you found the variant of your preference you can also wrap it into a function.
如果您找到了您偏好的变体,您还可以将其包装到一个函数中。
Here I'm wrapping some bashism into a div function:
在这里,我将一些 bashism 包装到一个 div 函数中:
One liner:
一个班轮:
function div { local _d=${3:-2}; local _n=0000000000; _n=${_n:0:$_d}; local _r=$(($_n/)); _r=${_r:0:-$_d}.${_r: -$_d}; echo $_r;}
Or multi line:
或多行:
function div {
local _d=${3:-2}
local _n=0000000000
_n=${_n:0:$_d}
local _r=$(($_n/))
_r=${_r:0:-$_d}.${_r: -$_d}
echo $_r
}
Now you have the function
现在你有了这个功能
div <dividend> <divisor> [<precision=2>]
and use it like
并像使用它一样
> div 1 2
.50
> div 273 123 5
2.21951
> x=$(div 22 7)
> echo $x
3.14
UPDATEI added a little script which provides you the basic operations with floating point numbers for bash:
更新我添加了一个小脚本,它为您提供了 bash 浮点数的基本操作:
Usage:
用法:
> 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
And here the script:
这里的脚本:
#!/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 [ "" == "/" ]; then
x1=$x1${z:0:$n}
fi
local r=$(($x1""$x2))
local l=$((${#r}-$n))
if [ "" == "*" ]; then
l=$(($l-$n))
fi
echo ${r:0:$l}.${r:$l}
}
add() { __op + ;}
sub() { __op - ;}
mul() { __op "*" ;}
div() { __op / ;}
回答by user3210339
It's not really floating point, but if you want something that sets more than one result in one invocation of bc...
它不是真正的浮点数,但是如果您想要在一次 bc 调用中设置多个结果的东西...
source /dev/stdin <<<$(bc <<< '
d=''*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a=''*''*3.1415926535897932384626433832795
print "a=",a,"\n"
')
echo bc radius: area:$a diameter:$d
computes the area and diameter of a circle whose radius is given in $1
计算半径为 $1 的圆的面积和直径