Как вы можете заставить bc следовать масштабу?

#bash #calculation #bc

#bash #вычисление #bc

Вопрос:

Я хочу вычислить процентное соотношение нескольких чисел с точностью до 2 знаков после запятой. Поскольку мое общее количество довольно велико, деление 100 на него дает действительно небольшое число (0.000 ..), поэтому для этого шага у меня большая шкала 10. На втором шаге, где я умножаю полученное число для вычисления процента, используется шкала как 2, но она игнорируется, поскольку bc использует первую шкалу, равную 10. Это код, который у меня есть:

 mul=$(bc <<< "scale=10; (100/$t)")

while read -r num var
do
perc=$(bc <<< "scale=2; ($num*$mul)")
printf "$vart$numt$percn" >> ofile
done < counts
  

Как я могу заставить второе вычисление следовать шкале и печатать с точностью до 2 знаков после запятой?

Ответ №1:

Отформатируйте числа с помощью printf:

 printf '%st%st%.2fn' "$var" "$num" "$perc" >> ofile
  

Ответ №2:

scale (общее количество десятичных цифр после запятой), используемое с bc, работает по-разному в зависимости от используемой арифметической операции.

выражение*expression

Результатом должно быть произведение двух выражений. Если a и b являются масштабами двух выражений, то масштаб результата должен быть:

min (a b,max(масштаб,a,b))

выражение / expression

Результатом должно быть частное от двух выражений. Масштабом результата должно быть значение scale.

Это причина различий в поведении вашего деления и вашего умножения в вашем коде.

Ответ №3:

Вы можете решить эту проблему, используя следующий «клудж»:

 a=3.2222222222
b=24.30123
foo=$(bc <<< "x = $a * $b; scale=2; (x * 100) / 100;")
echo $foo
  

Этот код выведет следующий вывод:

 78.30
  

Идея здесь в том, что результатом вычисления (x * 100) / 100 будет то же число, что и $a * $b (78.303963332793306
), но масштаб, который будет применен к нему на этот раз, будет равен 2, что фактически приведет к усечению всего, что у вас есть после двух знаков после запятой, что составит 78.30.

По причине того, что происходит с масштабом числа, которое вы получаете в результате умножения двух других чисел, смотрите Ответ Фергюсона.

Код, на самом деле, можно сделать еще короче:

 foo=$(bc <<< "scale=2; ($a * $b) / 1")
  

Это потому, что новое число, которое вы получите, — это gong, чтобы наследовать глобальный масштаб 2, который вы специально настроили.