bash 脚本和浮点除法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12147040/
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:36:27  来源:igfitidea点击:

Division in script and floating-point

bashshell

提问by Paris31

I would like to do the following operation in my script:

我想在我的脚本中执行以下操作:

1 - ((m - 20) / 34)

I would like to assign the result of this operation to another variable. I want my script use floating point math. For example, for m = 34:

我想将此操作的结果分配给另一个变量。我希望我的脚本使用浮点数学。例如,对于 m = 34:

results = 1 - ((34 - 20) / 34) == 0.588

回答by John Kugelman

You could use the bccalculator. It will do arbitrary precision math using decimals (not binary floating point) if you set increease scalefrom its default of 0:

你可以用bc计算器。如果将 increease 设置scale为默认值 0 ,它将使用小数(不是二进制浮点)进行任意精度数学运算:

$ m=34
$ bc <<< "scale = 10; 1 - (($m - 20) / 34)"
.5882352942

The -loption will load the standard math library and default the scale to 20:

-l选项将加载标准数学库并将比例默认为 20:

$ bc -l <<< "1 - (($m - 20) / 34)"
.58823529411764705883

You can then use printf to format the output, if you so choose:

然后,您可以使用 printf 来格式化输出,如果您这样选择:

printf "%.3f\n" "$(bc -l ...)"

回答by jordanm

Bash does not do floating point math. You can use awk or bc to handle this. Here is an awk example:

Bash 不进行浮点数学运算。您可以使用 awk 或 bc 来处理此问题。这是一个 awk 示例:

$ m=34; awk -v m=$m 'BEGIN { print 1 - ((m - 20) / 34) }'
0.588235

To assign the output to a variable:

要将输出分配给变量:

var=$(awk -v m=$m 'BEGIN { print 1 - ((m - 20) / 34) }')

回答by Cyrus

Teach bash e.g. integer division with floating point results:

用浮点结果教 bash 例如整数除法:

#!/bin/bash

div ()  # Arguments: dividend and divisor
{
        if [  -eq 0 ]; then echo division by 0; exit; fi
        local p=12                            # precision
        local c=${c:-0}                       # precision counter
        local d=.                             # decimal separator
        local r=$((/)); echo -n $r        # result of division
        local m=$(($r*))
        [ $c -eq 0 ] && [ $m -ne  ] && echo -n $d
        [  -eq $m ] || [ $c -eq $p ] && return
        local e=$((-$m))
        let c=c+1
        div $(($e*10)) 
}  

    result=$(div 1080 633)                  # write to variable
    echo $result

    result=$(div 7 34)
    echo $result

    result=$(div 8 32)
    echo $result

    result=$(div 246891510 2)
    echo $result

    result=$(div 5000000 177)
    echo $result

Output:

输出:

    1.706161137440
    0.205882352941
    0.25
    123445755
    28248.587570621468

回答by siraj md

echo $a/$b|bc -l

gives the result.

给出结果。

Example:

例子:

read a b
echo $a/$b|bc -l

Enter a & b value as 10 3, you get 3.3333333333

输入 a & b 值作为 10 3,你得到 3.3333333333

If you want to store the value in another variable then use the code

如果要将值存储在另一个变量中,请使用代码

read a b
c=`echo $a/$b|bc -l`
echo $c

It also gives the same result as above. Try it...

它也给出了与上面相同的结果。尝试一下...

回答by wmeitzen

I know this is an old thread, but this seemed like a fun project to tackle without using bcor invoking recursion. I'm sure it can be improved, but this maxed out my skill.

我知道这是一个旧线程,但这似乎是一个有趣的项目,无需使用bc或调用递归即可解决。我相信它可以改进,但这最大限度地发挥了我的技能。

numerator=5
denominator=7 # - 0 -> returns "undef"
decimal_places=4 # - 0 -> same as echo $(( $numerator / $denominator ))
_result_sign=""
let _dp_exp=10**decimal_places
if [ $denominator -eq 0 ]; then _div_result_int_large=0; else let _div_result_int_large=$((numerator * _dp_exp / denominator)); fi
if [ $_div_result_int_large -lt 0 ]; then let _div_result_int_large=$(( _div_result_int_large * -1 )); _result_sign="-"; fi
let _div_result_int=$((_div_result_int_large / _dp_exp))
let _div_result_mant=$((_div_result_int_large - _div_result_int * _dp_exp))
let _dp_lzeros=$((decimal_places - ${#_div_result_mant}))
printf -v _div_result_mant_padded "%.${_dp_lzeros}d$_div_result_mant"
div_result="$_result_sign$_div_result_int"
if [ $decimal_places -gt 0 ]; then div_result="$_result_sign$_div_result_int.$_div_result_mant_padded"; fi
if [ $denominator -eq 0 ]; then div_result="undef"; fi
echo $div_result

Example output:

示例输出:

numerator=5
denominator=7
decimal_places=5
-> 0.71428

numerator=250
denominator=13
decimal_places=0
-> 19

numerator=-5
denominator=6
decimal_places=2
-> -0.83

numerator=3
denominator=0 # - uh-oh
decimal_places=2 # - can be anything, in this case
-> undef

回答by minttux

Use this script open this file with favorite editor like:

使用此脚本使用最喜欢的编辑器打开此文件,例如:

$ sudo vim /usr/bin/div

Then paste this code:

然后粘贴此代码:

#!/bin/bash
# Author: Danial Rikhteh Garan ([email protected])

if [[ -z "" ]] || [[ -z "" ]]; then
    echo "Please input two number"
    echo "for 100/50 use: div 10 50"
    exit 1;
fi

div=$(echo "/" | bc -l);
echo 0$div | sed 's/[0]*$//g'

Now chmod it to 755:

现在将其修改为 755:

$ sudo chmod 755 /usr/bin/div

Now use it:

现在使用它:

$ div 5 100
0.05

In your script you can use this:

在你的脚本中,你可以使用这个:

var=$(div 5 100);
echo "$var"