在 Bash 中对被除数进行四舍五入
- 2024-10-29 08:34:00
- admin 原创
- 44
问题描述:
我该如何对两个数相除的结果进行舍入,例如
3/2
就像我做的那样
testOne=$((3/2))
$testOne 包含“1”,但它应该四舍五入为“2”,因为 3/2=1.5 的答案是
解决方案 1:
要在截断算术中进行四舍五入,只需将其添加(denom-1)
到分子即可。
例如,向下舍入:
N/2
M/5
K/16
例如,四舍五入:
(N+1)/2
(M+4)/5
(K+15)/16
要进行四舍五入,请添加(denom/2)
到分子(一半将向上舍入):
(N+1)/2
(M+2)/5
(K+8)/16
解决方案 2:
好的解决方案是获取最近的整数
var=2.5
echo $var | awk '{print int($1+0.5)}'
逻辑很简单,如果 var 十进制值小于 .5,则取最接近的值为整数值。如果十进制值大于 .5,则添加下一个整数值,因为 awk 只取整数部分。问题解决了
解决方案 3:
bash 不会给出正确的结果 3/2,因为它不进行浮点运算。你可以使用 awk 之类的工具
$ awk 'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2
或 bc
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2
解决方案 4:
如果对正数进行整数除法并将其四舍五入为零,则可以将除数减一添加到被除数上以使其向上舍入。
也就是说,X / Y
用替换(X + Y - 1) / Y
。
证明:
情况 1:
X = k * Y
(X 是 Y 的整数倍):在这种情况下,我们有(k * Y + Y - 1) / Y
,它分解为(k * Y) / Y + (Y - 1) / Y
。(Y - 1)/Y
部分四舍五入为零,我们得到 的商k
。 这正是我们想要的:当输入可整除时,我们希望调整后的计算仍然产生正确的精确商。情况 2:
X = k * Y + m
其中0 < m < Y
(X 不是 Y 的倍数)。在这种情况下,我们的分子为k * Y + m + Y - 1
,或k * Y + Y + m - 1
,我们可以将除法写为(k * Y)/Y + Y/Y + (m - 1)/Y
。由于0 < m < Y
,0 <= m - 1 < Y - 1
,因此最后一项(m - 1)/Y
趋于零。我们剩下的是(k * Y)/Y + Y/Y
,其结果为k + 1
。这表明该行为向上舍入。如果我们有一个 ,X
它是k
的倍数Y
,如果我们只向其添加 1,则除法将向上舍入为k + 1
。
但这种舍入方式恰恰相反;所有不精确的除法都会偏离零。介于两者之间的数字呢?
这可以通过用 来“启动”分子来实现Y/2
。 而不是X/Y
,计算(X+Y/2)/Y
。 我们不去证明,而是用经验来说明这一点:
$ 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
每当除数为偶数正数时,如果分子等于该数的一半,则向上舍入,如果分子小于该数,则向下舍入。
例如,round 6 12
趋向于1
,所有等于 的值也一样6
,模12
,像18
(趋向于 2)等等。 round 5 12
趋向于0
。
对于奇数,此行为是正确的。没有一个精确的有理数位于两个连续倍数的中间。例如,对于分母为,11
我们有5/11 < 5.5/11 (exact middle) < 6/11
;并且round 5 11
向下舍入,而round 6 11
向上舍入。
解决方案 5:
要进行四舍五入,您可以使用模数。
如果有余数,等式的第二部分将加为 True。(True = 1;False = 0)
例如:3/2
answer=$(((3 / 2) + (3 % 2 > 0)))
echo $answer
2
例如:100 / 2
answer=$(((100 / 2) + (100 % 2 > 0)))
echo $answer
50
例如:100 / 3
answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34
解决方案 6:
给定一个浮点值,我们可以使用以下方法简单地对其进行舍入printf
:
# round $1 to $2 decimal places
round() {
printf "%.${2:-0}f" "$1"
}
然后,
# 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
或者,使用原始请求:
$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)"
3/2, rounded to the nearest integer, is 2
解决方案 7:
如果小数分隔符是逗号(例如:LC_NUMERIC=fr_FR.UTF-8,请参见此处):
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
bash: printf: 1.50: nombre non valable
0
ghostdog74 解决方案需要替换:
$ printf "%.0f" $(echo "scale=2;3/2" | bc | sed 's/[.]/,/')
2
或者
$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2
解决方案 8:
另一个解决方案是在 Python 命令中执行除法。例如:
$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"
对我来说这比使用 awk 更不古老。
解决方案 9:
我想这就足够了。
$ echo "3/2" | bc
解决方案 10:
你可以使用这个函数r(x, p)
通过命令的手册页bc
:
r(x, p)
: Returns x rounded to p decimal places
这是一个例子。
#!/bin/bash
read expression
echo "r($expression,3)" | bc -l
执行脚本的结果5+50*3/20 + (19*2)/7
是17.929
注意:r(x, p)
在扩展库中实现,为了使用它,您应该使用 -l 或 --mathlib 标志:
All of the functions below, including the functions in the extended
math library (see the Extended Library subsection below), are available
when the -l or --mathlib command-line flags are given, except that the
extended math library is not available when the -s option, the -w
option, or equivalents are given.
解决方案 11:
以下对我有用。
#!/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
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件