如何在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:46:53  来源:igfitidea点击:

How do I use floating-point division in bash?

bashfloating-pointarithmetic-expressions

提问by Medya Gh

I am trying to divide two image widths in a Bash script, but bash gives me 0as 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 echoI tried to put the same thing in my SCALEbut 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, bashdoes 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 bcand awkalternatives there are also the following:

除了提到的bcawk替代方案外,还有以下几点:

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.

Stéphane Chazelas 在 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 -loption (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 的圆的面积和直径