Эти "пропускающие" строки совершенно нормальны.
Поиск некоторой строки намного быстрее, чем отображение каждой строки на экране. Поэтому, если вы ищете слово, less
просканирует файл на предмет этого слова и, как только найдет строку, отобразит только ту страницу строк, где было найдено слово.
Если вы прокрутите назад с помощью терминала, вы увидите эти «пропускающие» строки.
Если вы хотите вернуться в тексте назад, просто используйте соответствующие клавиши, например клавиши со стрелками. Это будет перемещать вас по тексту без каких-либо «пропусков».
PS: Вы можете ввести h в less
, чтобы просмотреть список ключей и их назначение.
FWIW,
prob=$(echo "0.0139" | bc)
не нужно - вы можете просто сделать
prob=0.0139
Eg,
$ prob=0.0139; echo "scale=5;1/$prob" | bc
71.94244
Есть еще одна проблема с вашим кодом, помимо проблемы с переполнением. Арифметика Bash может быть неадекватной для обработки больших чисел в вашей функции nCk2
. Например, на 32-битной системе передача 10 в эту функцию возвращает отрицательное число, -133461297271.
Чтобы справиться с проблемой неполного переполнения, вам нужно вычислять в большем масштабе, как упоминалось в других ответах. Для параметров, приведенных в ОП, достаточно масштаба от 25 до 30.
Я переписал ваш код, чтобы вся арифметика выполнялась в bc
. Вместо того чтобы просто передавать команды в bc
через echo
, я написал полный сценарий bc
как here document внутри сценария Bash, поскольку это упрощает передачу параметров из Bash в bc
.
#!/usr/bin/env bash
# Binomial probability calculations using bc
# Written by PM 2Ring 2015.07.30
n=144
p='1/72'
m=16
scale=30
bc << EOF
define ncr(n, r)
{
auto v,i
v = 1
for(i=1; i<=r; i++)
{
v *= n--
v /= i
}
return v
}
define binprob(p, n, r)
{
auto v
v = ncr(n, r)
v *= (1 - p) ^ (n - r)
v *= p ^ r
return v
}
sc = $scale
scale = sc
outscale = 8
n = $n
p = $p
m = $m
for(i=0; i<=m; i++)
{
v = binprob(p, n, i)
scale = outscale
print i,": ", v/1, "\n"
scale = sc
}
EOF
output
0: .13345127
1: .27066174
2: .27256781
3: .18171187
4: .09021610
5: .03557818
6: .01160884
7: .00322338
8: .00077747
9: .00016547
10: .00003146
11: .00000539
12: .00000084
13: .00000012
14: .00000001
15: 0
16: 0
n=144
prob=$(echo "0.0139" | bc)
echo -e "Enter no.:"
read passedno
k=$passedno
nCk2() {
num=1
den=1
for((i = 1; i <= $2; ++i)); do
((num *= $1 + 1 - i)) && ((den *= i))
done
echo $((num / den))
}
binomcoef=$(nCk2 $n $k)
binprobab=$(echo "$binomcoef*($prob^$k)*((1-$prob)^($n-$k))" | bc -l)
printf "%0.8f\n" $binprobab
Как вы знаете, это потому, что 0,0139 ^ 5 = .00000000051888844699
слишком мало и округлено до 0 с масштабом = 8
. Как насчет того, чтобы выполнить промежуточные вычисления с большим масштабом, а затем округлить последнее значение с помощью scale = 8
?
binprobab=$(echo "scale=20; a=$binomcoef*($prob^$k)*((1-$prob)^($n-$k)); scale=8; a/1" | bc)
Деление на 1 обычно используется для округления числа с масштабом
в bc.
Спасибо за объяснение, @voices. Решение awk с printf:
awk 'BEGIN {printf("%.2f\n",100*7/116)}'
Допустим, вы хотите вычислить, сколько процентов составляет 7 от 116.
Вы просто делите 7 на 116 и умножаете результат на 100.
Это должно быть примерно так:
bc -l <<< '(7/116)*100'
6.03448275862068965500
Вам нужна точность до двух знаков после запятой, поэтому вы добавляете scale=2;
, ожидая этого:
Но вы получаете какие-то странные результаты:
bc -l <<< 'scale=2; 100*(7/116)'
6.00
Вы пытаетесь увеличить значение scale
:
bc -l <<< 'scale=3; 100*(7/116)'
6.000
По какой-то причине scale=4;
имеет точность до 2-х знаков, но имеет эти конечные 0
с
bc -l <<< 'scale=4; 100*(7/116)'
6.0300
Первая часть вычислений имеет точность до 2 знаков после запятой, а остальные обрезаются.
Идеальным решением было бы, чтобы bash
/ sh
изначально поддерживали вычисления с плавающей запятой. Почему уже нет? Не имею представления. Кажется глупым не делать этого. До тех пор вы можете обойтись этим:
до н.э.
scale
. bc -l <<< "x=(7/116)*100; scale=2; x/1"
6.03
печать
bc
с помощью "$(
... )"
для подстановки команд. printf
. %.2f
в строке формата(%f
говорит с плавающей запятой, .2
говорит с точностью до 2 знаков после запятой (напримерscale=2
)). printf '%.2f\n' "$(bc -l <<< '(7/116)*100')"
6.03
авк
awk
тоже умеет считать echo
каким-то образом прерывает интерактивный цикл. Вероятно, есть лучший способ сделать это.echo | awk '{print 100*(7/116)}'
6.03448