Они не должны иметь доступ к каким-либо вашим файлам, вашей истории или тому, что содержится в вашем домашнем каталоге (настройки и т. д.). Я уверен, что если бы они были достаточно стойкими, они могли бы пройти, но я бы не стал беспокоиться об этом.
Самое простое решение:
printf %.2f $(echo "$float/1.18" | bc -l)
Bash / awk rounding:
echo "23.49" | awk '{printf("%d\n",$1 + 0.5)}'
Если у вас есть python, вы можете использовать что-то вроде этого:
echo "4.678923" | python -c "print round(float(raw_input()))"
Вот чисто bc-решение. Правила округления: при +/- 0,5, округлите от нуля.
Поместите масштаб, который вы ищете, в $ result_scale; ваша математика должна быть там, где $ MATH находится в списке команд bc:
bc <<MATH
h=0
scale=0
/* the magnitude of the result scale */
t=(10 ^ $result_scale)
/* work with an extra digit */
scale=$result_scale + 1
/* your math into var: m */
m=($MATH)
/* rounding and output */
if (m < 0) h=-0.5
if (m > 0) h=0.5
a=(m * t + h)
scale=$result_scale
a / t
MATH
Я знаю, что это старый вопрос, но у меня есть чистое «bc'-решение без« if »или ветвей:
#!/bin/sh
bcr()
{
echo "scale=$2+1;t=$1;scale-=1;(t*10^scale+((t>0)-(t<0))/2)/10^scale" | bc -l
}
Используйте его как bcr '2/3' 5 или bcr '0.666666' 2 -> (выражение, за которым следует масштаб)
Это возможно, потому что в bc (например, C / C ++) разрешено смешивать логические выражения в ваших вычислениях. Выражение ((t>0)-(t<0))/2) будет оцениваться до +/- 0,5 в зависимости от знака «t» и, следовательно, использовать правильное значение для округления.
#!/bin/bash
# - loosely based on the function "round()", taken from
# http://stempell.com/2009/08/rechnen-in-bash/
# - inspired by user85321 @ askubuntu.com (original author)
# and Aquarius Power
# the round function (alternate approach):
round2()
{
v=$1
vorig=$v
# if negative, negate value ...
(( $(bc <<<"$v < 0") == 1 )) && v=$(bc <<<"$v * -1")
r=$(bc <<<"scale=$3;(((10^$3)*$v/$2)+0.5)/(10^$3)")
# ... however, since value was only negated to get correct rounding, we
# have to add the minus sign again for the resulting value ...
(( $(bc <<< "$vorig < 0") == 1 )) && r=$(bc <<< "$r * -1")
env printf %.$3f $r
};
echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
round2 $float 1.18 2
echo && read -p "Press any key to continue..."
Это на самом деле просто: нет необходимости явно добавлять жесткий код «-0,5» для отрицательных чисел. Математически говоря, мы просто вычислим абсолютное значение аргумента и добавим 0.5, как обычно. Но поскольку у нас (к сожалению) нет встроенной функции abs() в нашем распоряжении (если мы не будем ее кодировать), мы просто отрицаем аргумент, если он отрицательный.
Кроме того, было очень тяжело работать с добавьте в качестве параметра (так как для моего решения я должен иметь возможность получить доступ к дивиденду и делителю отдельно). Вот почему мой скрипт имеет дополнительный третий параметр.
Я все еще ищу чистый bc ответ на то, как объединить только одно значение внутри функции, но вот чистый ответ bash:
#!/bin/bash
echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
embiggen() {
local int precision fraction=""
if [ "$1" != "${1#*.}" ]; then # there is a decimal point
fraction="${1#*.}" # just the digits after the dot
fi
int="${1%.*}" # the float as a truncated integer
precision="${#fraction}" # the number of fractional digits
echo $(( 10**10 * $int$fraction / 10**$precision ))
}
# round down if negative
if [ "$float" != "${float#-}" ]
then round="-5000000000"
else round="5000000000"
fi
# calculate rounded answer (sans decimal point)
answer=$(( ( `embiggen $float` * 100 + $round ) / `embiggen 1.18` ))
int=${answer%??} # the answer as a truncated integer
echo $int.${answer#$int} # reassemble with correct precision
read -p "Press any key to continue..."
В принципе, это тщательно извлекает десятичные числа, умножает все на 100 миллиардов (10¹⁰, 10**10 в bash), настраивается для точности и округления, выполняет фактическое деление, делит обратно на соответствующую величину и затем вставляет десятичное число.
[d2 ] Шаг за шагом:Функция embiggen() присваивает усеченную целочисленную форму своего аргумента $int и сохраняет числа после точки в $fraction. Число дробных цифр отмечено в $precision. Математика умножает 10¹⁰ на конкатенацию $int и $fraction, а затем корректирует это, чтобы соответствовать точности (например, embiggen 48.86 становится 10¹⁰ × 4886/100 и возвращает 488600000000, что составляет 488 600 000 000).
[d4 ] Мы хотим получить окончательную точность сотых, поэтому умножим первое число на 100, добавим 5 для округления, а затем разделим второе число. Это присвоение $answer оставляет нас в сто раз окончательный ответ.Теперь нам нужно добавить десятичную точку. Мы присваиваем новое значение $int для $answer, исключая его последние две цифры, затем echo с точкой и $answer, за исключением значения $int, которое уже было выполнено. (Не обращайте внимания на ошибку подсветки синтаксиса, которая делает это похожим на комментарий)
(Башизм: возведение в степень не является POSIX, поэтому это базис. Чистое решение POSIX требует, чтобы циклы добавляли нули, а не использовали полномочия из десяти.Кроме того, «embiggen» - это отличное кромовое слово.)
Одна из основных причин, по которым я использую zsh, как свою оболочку, заключается в том, что она поддерживает математику с плавающей запятой. Решение этого вопроса довольно прямолинейно в zsh:
printf %.2f $((float/1.18))
(я бы хотел, чтобы кто-то добавил комментарий к этому ответу с трюком, чтобы включить арифметику с плавающей запятой в bash, но я уверен, что такой функции еще не существует.)
, если у вас есть результат, например, рассмотрите 2.3747888
все, что вам нужно сделать, это:
d=$(echo "(2.3747888+0.5)/1" | bc); echo $d
округляет число правильно:
десятичные знаки удаляются с помощью bc и поэтому округляются до 2, так как он должен иметь
Мне пришлось рассчитать общую продолжительность коллекции аудиофайлов.
Поэтому мне пришлось:
A. получить продолжительность для каждого файла (не показана)
B. (все они были в NNN.NNNNNN (fp) секунды)
C. отдельные часы, минуты, секунды, подсегменты.
D. выводит строку HR: MIN: SEC: FRAMES, где frame = 1/75 с.
не показано
A: используйте ffprobe и строку длительности разбора в число fp (не показано)
B:
# add them up as a series of strings separated by "+" and send it to bc
arr=( "${total[@]}" ) # copy array
# IFS is "Internal Field Separator"
# the * in arr[*] means "all of arr separated by IFS"
# must have been made for this
IFS='+' sum=$(echo "scale=3; ${arr[*]} "| bc -l)# (-l= libmath for fp)
echo $sum
C:
# subtract each amount of time from tt and store it
tt=$sum # tt is a running var (fp)
hrs=$(echo "$tt / 3600" | bc)
tt=$(echo "$tt - ( $hrs * 3600 )" | bc )
min=$(echo "$tt / 60" | bc )
tt=$(echo "$tt - ($min *60)" | bc )
sec=$(echo "$tt/1" | bc )
tt=$(echo "$tt - $sec" | bc )
frames=$(echo "$tt * 75" | bc ) # 75 frames /sec
frames=$(echo "$frames/1" | bc ) # truncate to whole #
D :
#convert to proper format with printf (bash builtin)
hrs=$(printf "%02d\n" $hrs) # format 1 -> 01
min=$(printf "%02d\n" $min)
sec=$(printf "%02d\n" $sec)
frames=$(printf "%02d\n" $frames)
timecode="$hrs:$min:$sec:$frames"
# timecode "01:13:34:54"
Ниже приведена сокращенная версия вашего скрипта, исправленная для предоставления нужного вам результата:
#!/bin/bash
float=48.86
echo "You asked for $float; This is the price without taxes:"
echo "scale=3; price=$float/1.18 +.005; scale=2; price/1 " | bc
Обратите внимание, что округление до ближайшего целого эквивалентно добавлению .5 и получению или округлению (для положительных чисел).
Кроме того, коэффициент масштабирования применяется во время работы; поэтому (это команды bc, вы можете вставить их в свой терминал):
float=48.86; rate=1.18;
scale=2; p2=float/rate
scale=3; p3=float/rate
scale=4; p4=float/rate
print "Compare: ",p2, " v ", p3, " v ", p4
Compare: 41.40 v 41.406 v 41.4067
# however, scale does not affect an entered value (nor addition)
scale=0
a=.005
9/10
0
9/10+a
.005
# let's try rounding
scale=2
p2+a
41.405
p3+a
41.411
(p2+a)/1
41.40
(p3+a)/1
41.41
Чистая реализация bc по запросу
define ceil(x) { auto os,xx;x=-x;os=scale;scale=0 xx=x/1;if(xx>x).=xx-- scale=os;return(-xx) }
, если вы поместите ее в файл с именем functions.bc, то вы можете округлить с помощью
[ f2]
Код для реализации bc найден на http://phodd.net/gnu-bc/code/funcs.bc