не может заставить сложный расчет работать в bc

Я использую qalculate в качестве своего повседневного калькулятора, и это здорово! Достаточно просто ввести что-то вроде:

(1+10^(-17.2/20)) / (1-10^(-17.2/20))

и получить правильный ответ:

1.320289

Но попытка заставить bc выполнять такие вычисления в сценарии bash разочаровывает. Поиск Google выдает много страниц, демонстрирующих простейшие математические примеры с использованием bc, но я еще не нашел ни одной страницы, посвященной выполнению более сложных вычислений. Когда я набираю в CL следующее:

echo 'scale=50; (1+10^(-17.2/20)) / (1-10^(-17.2/20))' | bc -l

Я получаю следующие предупреждения-ошибки:

Runtime warning (func=(main), adr=25): non-zero scale in exponent
Runtime warning (func=(main), adr=44): non-zero scale in exponent
Runtime error (func=(main), adr=46): Divide by zero

Если я попробую что-то подобное, но немного проще, например:

echo '(1-10^(-17.2/20))' | bc -l

Я получаю ответ, но он неправильный и сопровождается предупреждением.

Runtime warning (func=(main), adr=18): non-zero scale in exponent
0

С чем у bc могут быть проблемы, или, скорее, что я делаю неправильно, чтобы заставить bc правильно выполнять эти вычисления?


person scriptz    schedule 19.01.2015    source источник


Ответы (2)


со страницы руководства bc:

expr ^ expr: Результатом выражения является значение первого, возведенное во второе. Второе выражение должно быть целым числом.

но так как если x = a^b, то ln(x) = ln(a^b) = b(ln(a)), мы можем видеть, что x = exp(b(ln(a))), поэтому, если вы хотите увеличить число до дробных b, вы можете использовать это.

Примечание. В bc фактическими функциями exp и ln являются e и l.

person genisage    schedule 19.01.2015
comment
производство: echo 'a=10; b=-17.2/20; x=e(b*l(a)); (1+x)/(1-x)' | bc -l - person glenn jackman; 20.01.2015
comment
Я уверен, что есть очень веские причины для того, как bc требует ввода своих вычислений, но по сравнению с решением awk, представленным ниже, способ bc для ввода вычислений не читается или не кажется очень интуитивным, а скорее непрозрачным и неуклюжим. И без того сложный расчет стал еще более трудным для выполнения. Если нет каких-либо серьезных недостатков, использующих awk для сложных вычислений, это выглядит как победитель между ними. - person scriptz; 20.01.2015
comment
Преимущество @scriptz bc заключается в том, что он может быть сколь угодно точным. Если вам это не нужно, решение awk, вероятно, лучше. - person genisage; 20.01.2015

К сожалению, bc не поддерживает такие экспоненты, как -17.2/20. Если вам не требуется точность 50 знаков после запятой, можно использовать другой инструмент, например awk:

$ awk 'BEGIN{print (1+10^(-17.2/20)) / (1-10^(-17.2/20))}'
1.32029

Вы можете передавать переменные в awk из своего скрипта следующим образом:

$ awk -va="-17.2" -vb="20" 'BEGIN{print (1+10^(a/b)) / (1-10^(a/b))}'
1.32029
person Tom Fenech    schedule 19.01.2015
comment
Мне нужно сделать что-то вроде: awk -va="$1" 'BEGIN{print (1+10^(a/20)) / (1-10^(a/20))}' чтобы создать псевдоним .bashrc, который использует значение var $1, предоставленное пользователем, когда команда вводится на терминале. Это, однако, возвращает только значение inf независимо от того, что я предоставляю как var $1. Если я смогу заставить это работать, тогда нет необходимости в сценарии, чтобы сделать то же самое. - person scriptz; 20.01.2015
comment
отлично работает, вызывая пользовательский ввод $1 в сценарии bash, но я все же думаю, что псевдоним был бы более эффективным. - person scriptz; 20.01.2015
comment
@scriptz, вместо псевдонима можно использовать функцию: function test() { awk -va=$1 -vb=$2 'BEGIN{print (1+10^(a/b)) / (1-10^(a/b ))}'; } - person Udi; 18.05.2016