Завершить разделенное число в Bash - программирование
Подтвердить что ты не робот

Завершить разделенное число в Bash

Как бы я округлял результат от двух разделенных чисел, например.

3/2

Как и я,

testOne=$((3/2))

$testOne содержит "1", когда он должен округлить до "2" в качестве ответа от 3/2 = 1,5

4b9b3361

Ответ 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

bash не даст вам правильного результата 3/2, поскольку он не выполняет плавающие математические вычисления. вы можете использовать такие инструменты, как awk

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

или bc

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

Ответ 3

Хорошее решение - получить ближайший круглый номер

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

Логика проста, если десятичное значение var меньше .5, то самое близкое значение будет целочисленным. Хорошо, если десятичное значение больше .5, то добавляется следующее целочисленное значение, а поскольку awk принимает только целую часть. Проблема решена.

Ответ 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

Учитывая значение с плавающей запятой, мы можем тривиально округлить его с помощью 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

Ответ 6

Другим решением является деление внутри команды python. Например:

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

Мне кажется менее архаичным, чем использование awk.

Ответ 7

Для округления вы можете использовать модуль.

Вторая часть уравнения добавит 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

Ответ 8

Я думаю, этого должно быть достаточно.

$ echo "3/2" | bc 

Ответ 9

Если десятичный разделитель является запятой (например: 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