Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在bash中使用浮点除法?_Bash_Floating Point_Arithmetic Expressions - Fatal编程技术网

如何在bash中使用浮点除法?

如何在bash中使用浮点除法?,bash,floating-point,arithmetic-expressions,Bash,Floating Point,Arithmetic Expressions,我试图在Bash脚本中划分两个图像宽度,但是Bash给了我0,结果是: RESULT=$(($IMG_WIDTH/$IMG2_WIDTH)) 我确实研究了Bash指南,我知道我应该使用bc,在互联网上的所有示例中,他们都使用bc。在echo中,我试图将同样的东西放入量表中,但没有成功 以下是我在教程中找到的示例: echo "scale=2; ${userinput}" | bc 我怎样才能让Bash给我一个类似0.5的浮点值?你不能。bash只处理整数;您必须委托给工具,如bc您可以执行

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

RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
我确实研究了Bash指南,我知道我应该使用
bc
,在互联网上的所有示例中,他们都使用
bc
。在
echo
中,我试图将同样的东西放入
量表中,但没有成功

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

echo "scale=2; ${userinput}" | bc 
我怎样才能让Bash给我一个类似
0.5
的浮点值?

你不能。bash只处理整数;您必须委托给工具,如
bc

您可以执行以下操作:

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

现在正是尝试zsh的最佳时机,zsh是一个(几乎)bash超集,具有许多额外的优秀特性,包括浮点数学。以下是您在zsh中的示例:

% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875

这篇文章可能会帮助你:

你可以通过
-l
选项(l字母)使用bc


作为bc的替代方案,您可以在脚本中使用awk

例如:

echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'
在上面的例子中,“%.2f”告诉printf函数返回小数点后两位的浮点数。我使用echo将变量作为字段导入,因为awk可以正确地对它们进行操作。“$1”和“$2”指输入awk的第一个和第二个字段

您可以使用以下命令将结果存储为其他变量:

RESULT = `echo ...`

它不是真正的浮点,但如果您希望在一次bc调用中设置多个结果

source /dev/stdin <<<$(bc <<< '
d='$1'*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a='$1'*'$1'*3.1415926535897932384626433832795
print "a=",a,"\n"
')

echo bc radius:$1 area:$a diameter:$d

source/dev/stdin稍微改进一下marvin的答案:

RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")

bc并不总是作为已安装的软件包出现。

在某些情况下,您不能使用bc,因为它可能根本不存在,例如在某些精简版本的busybox或嵌入式系统中。在任何情况下,限制外部依赖总是一件好事,因此您可以始终将零添加到被除的数字(分子),这与乘以10的幂(您应该根据需要的精度选择10的幂)相同,这将使除法输出为整数。一旦你有了这个整数,就把它当作一个字符串,把小数点的位置(从右向左移动)乘以十的幂,你就可以把分子乘以。这是一种仅使用整数获得浮点结果的简单方法。

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

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

.33
有关类似但更简洁的方法,请参见

选择 除了上述的
bc
awk
备选方案外,还有以下几种:

克里普 已清理的输出:

clisp --quiet -x '(/ 1.0 3)'
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
或通过
stdin

echo '(/ 1.0 3)' | clisp --quiet | tail -n1
echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }
echo 'print $(( 1/3. ))' | zsh
直流电 genius cli计算器 鬼书 gnuplot Imagemagick 或通过
stdin

echo '(/ 1.0 3)' | clisp --quiet | tail -n1
echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }
echo 'print $(( 1/3. ))' | zsh
jq 或:

ksh 卢阿 或通过stdin:

echo 'print(1/3)' | lua
极大值 已清理的输出:

clisp --quiet -x '(/ 1.0 3)'
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
节点 八度 perl 蟒蛇2 蟒蛇3 R 已清理的输出:

clisp --quiet -x '(/ 1.0 3)'
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
红宝石 单位 具有紧凑的输出:

units --co 1/3
wcalc 已清理的输出:

clisp --quiet -x '(/ 1.0 3)'
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
zsh 或通过
stdin

echo '(/ 1.0 3)' | clisp --quiet | tail -n1
echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }
echo 'print $(( 1/3. ))' | zsh
#其他来源


在Unix.SX上。

嗯,在float之前是使用固定小数逻辑的时期:

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
IMG_宽度=100
IMG2_宽度=3
整数=$($IMG\u WIDTH/$IMG2\u WIDTH))

DECIMAL=$(tail-c3虽然在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))
!/bin/bash
n=1美元
d=2美元
#由于四舍五入,这应该是10^{i+1}
#其中i是所需的小数位数
i=4
P=$((10**(i+1)))
Pn=$($P/10))
#在这里,我们“固定”小数位,对tward零进行除法和四舍五入
t=$($n*$P/$d+($n<0-5:5)))
#然后,我们将整数部分除以
#使用模运算符(在删除舍入数字后)获取派系部分。
printf“%d.%0${i}d\n”$($t/$P))$((t<0?-t:t)/10%$Pn))

如果您找到了首选项的变体,也可以将其包装到函数中

在这里,我将一些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>]
更新 我添加了一个小脚本,它为您提供了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 / ;}
!/bin/bash
__op(){
本地z=00000000000000000000
本地a1=${1%.*}
本地x1=${1/./}
局部n1=$(${x1}-${a1}))
本地a2=${2%.*}
本地x2=${2/./}
局部n2=$(${{x2}-${a2}))
本地n=$n1
如果($n1<$n2));则
本地n=$n2
x1=$x1${z:0:$($n2-$n1))}
fi
如果($n1>$n2));则
x2=$x2${z:0:$($n1-$n2))}
fi
如果[“$3”==“/”],则
x1=$x1${z:0:$n}
fi
本地r=$($x1“$3”$x2))
局部l=$(${r}-$n))
如果[“$3”==“*”];则
l=$($l-$n))
fi
echo${r:0:$l}.${r:$l}
}
add(){uuuu op$1$2+;}
sub(){uuuu op$1$2-;}
mul(){uuuu op$1$2“*”;}
div(){uuuu op$1$2/;}

这里是awk命令:-F=字段分隔符==+

echo "2.1+3.1" |  awk -F "+" '{print ($1+$2)}'

用计算器,这是我找到的最简单的 例如:

计算1+1

计算1/10


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

$IMG_WIDTH=1024
$IMG2_WIDTH=2048

$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"
像这样,在点后得到2位数字,在纯bash中被截断(称为舍入到较低的值)(无需启动其他进程)。当然,如果在点后只需要一位数字,则乘以10并进行模10运算

它的作用是:

  • 首先,
    $(…)
    进行整数除法
  • 第二个
    $(…)div <dividend> <divisor> [<precision=2>]
    
    > div 1 2
    .50
    
    > div 273 123 5
    2.21951
    
    > x=$(div 22 7)
    > echo $x
    3.14
    
    > 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 / ;}
    
    echo "2.1+3.1" |  awk -F "+" '{print ($1+$2)}'
    
     2
    
     0.1
    
    $IMG_WIDTH=1024
    $IMG2_WIDTH=2048
    
    $RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"
    
     pi=$(echo "scale=10; 4*a(1)" | bc -l)
    
     pi=$(echo "scale=10; 4*a(1)" | bc -l); echo $pi
     3.1415926532
    
     pi=$(printf %.4f $(echo "4*a(1)" | bc -l)); echo $pi
     3.1416
    
    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
    
    A=5.2
    B=4.3
    
    # Awk: Map variable into awk
    # Exit 0 (or just exit) for success, non-zero for error.
    #
    awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'
    
    # Perl
    perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"
    
    # Python 2
    python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"
    
    # Python 3
    python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"
    
    # BC
    bc <<< "scale=1 ; $A + $B * 0.1"
    
    echo "scale=2; (100/180) * 180" | bc
    
    echo "result = (100/180) * 180; scale=2; result / 1" | bc -l