Как бы я округлял результат от двух разделенных чисел, например.
3/2
Как и я,
testOne=$((3/2))
$testOne содержит "1", когда он должен округлить до "2" в качестве ответа от 3/2 = 1,5
Как бы я округлял результат от двух разделенных чисел, например.
3/2
Как и я,
testOne=$((3/2))
$testOne содержит "1", когда он должен округлить до "2" в качестве ответа от 3/2 = 1,5
Чтобы выполнить округление в усеченной арифметике, просто добавьте (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
bash не даст вам правильного результата 3/2, поскольку он не выполняет плавающие математические вычисления. вы можете использовать такие инструменты, как awk
$ awk 'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2
или bc
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2
Хорошее решение - получить ближайший круглый номер
var=2.5
echo $var | awk '{print int($1+0.5)}'
Логика проста, если десятичное значение var меньше .5, то самое близкое значение будет целочисленным. Хорошо, если десятичное значение больше .5, то добавляется следующее целочисленное значение, а поскольку awk принимает только целую часть. Проблема решена.
Если у вас есть целочисленное деление положительных чисел, которое округляется к нулю, то вы можете добавить один меньше дивизора к дивиденду, чтобы округлить его.
То есть замените 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
округляется.
Учитывая значение с плавающей запятой, мы можем тривиально округлить его с помощью printf:
# round $1 to $2 decimal places
round() {
printf "%.$2f" "$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
Другим решением является деление внутри команды python. Например:
$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"
Мне кажется менее архаичным, чем использование awk.
Для округления вы можете использовать модуль.
Вторая часть уравнения добавит True, если есть остаток. (True = 1; False = 0)
ex: 3/2
answer=$(((3 / 2) + (3 % 2 > 0)))
echo $answer
2
ex: 100/2
answer=$(((100 / 2) + (100 % 2 > 0)))
echo $answer
50
ex: 100/3
answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34
Я думаю, этого должно быть достаточно.
$ echo "3/2" | bc
Если десятичный разделитель является запятой (например: 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