简体   繁体   English

在 Bash 中舍入除数

[英]Round a divided number in Bash

How would I round the result from two divided numbers, eg我将如何从两个相除的数字中取整结果,例如

3/2

As when I do就像我做的那样

testOne=$((3/2))

$testOne contains "1" when it should have rounded up to "2" as the answer from 3/2=1.5 $testOne 包含“1”,而它应该四舍五入为“2”作为 3/2=1.5 的答案

To do rounding up in truncating arithmetic, simply add (denom-1) to the numerator.要在截断算术中进行四舍五入,只需将(denom-1)添加到分子。

Example, rounding down:示例,四舍五入:

N/2
M/5
K/16

Example, rounding up:示例,四舍五入:

(N+1)/2
(M+4)/5
(K+15)/16

To do round-to-nearest, add (denom/2) to the numerator (halves will round up):要进行四舍五入,请将(denom/2)添加到分子(一半将向上取整):

(N+1)/2
(M+2)/5
(K+8)/16

Good Solution is to get Nearest Round Number is好的解决方案是获得最近的整数是

var=2.5
echo $var | awk '{print int($1+0.5)}'

Logic is simple if the var decimal value is less then .5 then closest value taken is integer value.如果 var 十进制值小于 0.5,则逻辑很简单,则采用的最接近的值是整数值。 Well if decimal value is more than .5 then next integer value gets added and since awk then takes only integer part.好吧,如果十进制值大于 0.5,则添加下一个整数值,因为 awk 只取整数部分。 Issue solved问题已解决

bash will not give you correct result of 3/2 since it doesn't do floating pt maths. bash 不会给你 3/2 的正确结果,因为它不做浮动 pt 数学。 you can use tools like awk你可以使用awk之类的工具

$ awk  'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2

or bc或公元前

$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2

If you have integer division of positive numbers which rounds toward zero, then you can add one less than the divisor to the dividend to make it round up.如果您有向零舍入的正数的整数除法,那么您可以在被除数上加上比除数少 1 以使其四舍五入。

That is to say, replace X / Y with (X + Y - 1) / Y .也就是说,将X / Y替换为(X + Y - 1) / Y

Proof:证明:

  • Case 1: X = k * Y (X is integer multiple of Y): In this case, we have (k * Y + Y - 1) / Y , which splits into (k * Y) / Y + (Y - 1) / Y .情况 1: X = k * Y (X 是X = k * Y整数倍):在这种情况下,我们有(k * Y + Y - 1) / Y ,分为(k * Y) / Y + (Y - 1) / Y The (Y - 1)/Y part rounds to zero, and we are left with a quotient of k . (Y - 1)/Y部分四舍五入为零,我们剩下的商为k This is exactly what we want: when the inputs are divisible, we want the adjusted calculation to still produce the correct exact quotient.这正是我们想要的:当输入可整除时,我们希望调整后的计算仍然产生正确的精确商。

  • Case 2: X = k * Y + m where 0 < m < Y (X is not a multiple of Y).情况 2: X = k * Y + m ,其中0 < m < Y (X 不是 Y 的倍数)。 In this case we have a numerator of k * Y + m + Y - 1 , or k * Y + Y + m - 1 , and we can write the division out as (k * Y)/Y + Y/Y + (m - 1)/Y .在这种情况下,我们有一个k * Y + m + Y - 1k * Y + Y + m - 1的分子,我们可以将除法写为(k * Y)/Y + Y/Y + (m - 1)/Y Since 0 < m < Y , 0 <= m - 1 < Y - 1 , and so the last term (m - 1)/Y goes to zero.由于0 < m < Y0 <= m - 1 < Y - 1 ,所以最后一项(m - 1)/Y变为零。 We are left with (k * Y)/Y + Y/Y which work out to k + 1 .我们剩下(k * Y)/Y + Y/Y ,结果为k + 1 This shows that the behavior rounds up.这表明该行为四舍五入。 If we have an X which is a k multiple of Y , if we add just 1 to it, the division rounds up to k + 1 .如果我们有一个XYk Y ,如果我们只给它加 1,除法会向上k + 1整为k + 1

But this rounding is extremely opposite;但这种四舍五入是极其相反的; all inexact divisions go away from zero.所有不精确的除法都从零开始。 How about something in between?介于两者之间怎么样?

That can be achieved by "priming" the numerator with Y/2 .这可以通过用Y/2 “启动”分子来实现。 Instead of X/Y , calculate (X+Y/2)/Y .而不是X/Y ,计算(X+Y/2)/Y Instead of proof, let's go empirical on this one:代替证明,让我们对这一点进行实证:

$ round()
> {
>   echo $((($1 + $2/2) / $2))
> }
$ round 4 10
0
$ round 5 10
1
$ round 6 10
1
$ round 9 10
1
$ round 10 10
1
$ round 14 10
1
$ round 15 10
2

Whenever the divisor is an even, positive number, if the numerator is congruent to half that number, it rounds up, and rounds down if it is one less than that.当除数是偶数、正数时,如果分子等于该数的一半,则向上舍入,如果小于 1,则向下舍入。

For instance, round 6 12 goes to 1 , as do all values which are equal to 6 , modulo 12 , like 18 (which goes to 2) and so on.例如, round 6 12等于1 ,所有等于6值也是如此,取模12 ,例如18 (等于 2)等等。 round 5 12 goes down to 0 . round 5 12下降到0

For odd numbers, the behavior is correct.对于奇数,行为是正确的。 None of the exact rational numbers are midway between two consecutive multiples.没有一个精确的有理数介于两个连续的倍数之间。 For instance, with a denominator of 11 we have 5/11 < 5.5/11 (exact middle) < 6/11 ;例如,当分母为11我们有5/11 < 5.5/11 (exact middle) < 6/11 and round 5 11 rounds down, whereas round 6 11 rounds up. round 5 11轮向下round 6 11 ,而round 6 11轮向上round 6 11

To round up you can use modulus.要四舍五入,您可以使用模数。

The second part of the equation will add to True if there's a remainder.如果有余数,等式的第二部分将与 True 相加。 (True = 1; False = 0) (真 = 1;假 = 0)

ex: 3/2例如:3/2

answer=$(((3 / 2) + (3 % 2 > 0)))
echo $answer
2

ex: 100 / 2例如:100 / 2

answer=$(((100 / 2) + (100 % 2 > 0)))
echo $answer
50

ex: 100 / 3例如:100 / 3

answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34

Given a floating point value, we can round it trivially with printf :给定一个浮点值,我们可以用printf对其进行四舍五入:

# round $1 to $2 decimal places
round() {
    printf "%.${2:-0}f" "$1"
}

Then,然后,

# do some math, bc style
math() {
    echo "$*" | bc -l
}

$ echo "Pi, to five decimal places, is $(round $(math "4*a(1)") 5)"
Pi, to five decimal places, is 3.14159

Or, to use the original request:或者,使用原始请求:

$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)"
3/2, rounded to the nearest integer, is 2

If the decimal separator is comma (eg : LC_NUMERIC=fr_FR.UTF-8, see here ):如果小数点分隔符是逗号(例如:LC_NUMERIC=fr_FR.UTF-8,请参见此处):

$ printf "%.0f" $(echo "scale=2;3/2" | bc) 
bash: printf: 1.50: nombre non valable
0

Substitution is needed for ghostdog74 solution : ghostdog74 解决方案需要替换:

$ printf "%.0f" $(echo "scale=2;3/2" | bc | sed 's/[.]/,/')
2

or或者

$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2

Another solution is to do the division within a python command.另一种解决方案是在 python 命令中进行除法。 For example:例如:

$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"

Seems less archaic to me than using awk.对我来说似乎不如使用 awk 过时。

我认为这应该足够了。

$ echo "3/2" | bc 

Following worked for me.以下为我工作。

 #!/bin/bash
function float() {
bc << EOF
num = $1;
base = num / 1;
if (((num - base) * 10) > 1 )
    base += 1;
print base;
EOF
echo ""
}

float 3.2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM