Как мне округлить результат из двух разделенных чисел, например.
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
testOne=$(( (3 + (2 - 1) / 2))
. В более общем смысле, но в синтаксисе Bash это будет что-то вроде answer=$(( ($numerator + ($denominator - 1) / $denomonator))
. Вы также можете сделать это таким образом, чтобы исключить все знаки доллара и предоставить больше свободы с пробелами (например, вокруг знака равенства): ((answer = (numerator + (denominator - 1) / denomonator))
- person Dennis Williamson; 07.03.2010
testOne=$(( (3 + (2 - 1) / 2))
правильно: testOne=$(( (3 + (2 - 1)) / 2))
- person Pro Backup; 05.03.2017
Хорошее решение - получить ближайшее круглое число
var=2.5
echo $var | awk '{print int($1+0.5)}'
Логика проста, если десятичное значение var меньше 0,5, тогда ближайшее значение является целым числом. Что ж, если десятичное значение больше 0,5, то добавляется следующее целое значение, и, поскольку awk принимает только целую часть. Проблема решена
bash не даст вам правильного результата 3/2, так как он не выполняет математику с плавающей запятой. вы можете использовать такие инструменты, как awk
$ awk 'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2
or bc
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2
awk 'BEGIN { rounded = sprintf("%.0f", 1.000001/2); print rounded }'
возвращает 1
- person Kar.ma; 06.04.2017
$ echo 4.5 |awk '{printf "%.0f",$0}'
дает 4, а $ echo 5.5 |awk '{printf "%.0f",$0}'
дает 6 — округляет 0,5 до ближайшего четного целого числа.
- person unhammer; 16.11.2018
Если у вас есть целочисленное деление положительных чисел, которое округляется до нуля, то вы можете добавить к делимому на единицу меньше, чем делитель, чтобы округлить его в большую сторону.
То есть заменить 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
округляется вверх.
round x y
берет x
, деленное на y
, и округляет до ближайшего целого числа.
- person Ro Yo Mi; 30.07.2019
Чтобы округлить, вы можете использовать модуль.
Вторая часть уравнения добавит к True, если есть остаток. (Истина = 1; Ложь = 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
Учитывая значение с плавающей запятой, мы можем тривиально округлить его с помощью 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
printf "%.0f" "0.5"
печатает 0
вместо ожидаемого 1
, а printf "%.0f" "0.6"
печатает 1
как и ожидалось.
- person Alexej Magura; 11.11.2016
printf "%.2f" "$1"
неправильно :printf "%.0f" "2.6"
: bash: printf: 2.6: invalid number
.
- person pevik; 18.09.2019
printf "%.${2:-0}f" "$1"
. Я не могу изменить 1 символ :-(
- person Marco; 22.01.2020
Если десятичным разделителем является запятая (например: 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
or
$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2
Другое решение - выполнить деление внутри команды Python. Например:
$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"
Мне кажется менее архаичным, чем использование awk.
Я думаю, этого должно быть достаточно.
$ echo "3/2" | bc
echo "2.5*3" | bc
дает 7.5
- person mhwombat; 08.08.2014
Следующее сработало для меня.
#!/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