разные результаты расчета с использованием bc в скрипте и консоли

В сценарии, который я сейчас пишу, мне нужны десятичные вычисления, поэтому я решил использовать bc. Я не знаком с этим инструментом, поэтому простите меня, если вопрос тривиален.
Когда я использую консоль и набираю:

установить r_m=`echo "масштаб=6; $pd_f*$d_f*(1/sqrt(3))+($fr_numb-1)*($pd_f*$d_f*(1/sqrt(3))+$pd_f *$d_f*0,5*(s(3,14159265*30/180)/c(3,14159265*30/180)))+0,4"|bc -l`

затем echo "$r_m" это дает мне: 19.849870
($pd_f и $d_f были объявлены 1.129 и 1.126 соответственно раньше, о, и $fr_numb=18)

но (!) используя те же строки в сценарии bash:

r_m=`echo "scale=6; $pd_f*$d_f*(1/sqrt(3))+($fr_numb-1)*($pd_f*$d_f*(1/sqrt(3))+$pd_f* $d_f*0,5*(s(3,14159265*30/180)/c(3,14159265*30/180)))+0,4"|bc -l`

дает мне: .033022

Почему?

ОБНОВЛЕНИЕ Я заключил все после = в обратные кавычки. Раньше я не знал, как использовать их в блок-цитатах.

Оболочка bash 2.05


person kasper    schedule 19.02.2011    source источник
comment
Какая оболочка использует вашу консоль? Если я наберу ваш пример, он даст мне (standard_in) 1: syntax error (четыре раза). Итак, какие значения имеют переменные $pd_f, $d_f, $fr_numb?   -  person Paŭlo Ebermann    schedule 19.02.2011
comment
@Paŭlo Ebermann: я обновил вопрос. Теперь это не должно вызывать синтаксических ошибок. Как я уже сказал, эти переменные были установлены ранее и представляют собой простые числа.   -  person kasper    schedule 19.02.2011


Ответы (4)


Этот скрипт

#!/bin/bash

pd_f=1.129
d_f=1.126
fr_numb=18

r_m=`echo "scale=6; $pd_f*$d_f*(1/sqrt(3))+($fr_numb-1)*($pd_f*$d_f*(1/sqrt(3))+$pd_f*$d_f*0.5*(s(3.14159265*30/180)/c(3.14159265*30/180)))+0.4"|bc -l`

echo $r_m

выводит 19.849870 на

GNU bash, Version 4.1.5(1)-release (i686-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.

точно так же, как вывод при вводе его на (управляемой bash) консоли. Может надо экспортировать переменные перед вызовом своего скрипта, если они в нем не определены, а только в окружающей оболочке?

person Paŭlo Ebermann    schedule 19.02.2011
comment
Если я запускаю уравнение из консоли, я устанавливаю переменные в консоли перед вычислениями. Если я запускаю его внутри скрипта, я также устанавливаю $pd_f, $d_f и fr_numb раньше. - person kasper; 19.02.2011
comment
О, я еще раз перепроверил и обнаружил, что fr_numb был объявлен неправильно. Сейчас хорошо. Спасибо - person kasper; 19.02.2011

Я получаю результат .033022, когда fr_numb=0.

Кстати, ваша интерактивная команда явно запускается в csh. Вы должны убедиться, что ваш сценарий имеет следующую строку в качестве первой строки, если вы хотите убедиться, что он запускается Bash:

#!/bin/bash

Кроме того, используйте пробелы и продолжение строки, чтобы сделать формулу более читабельной.

#!/bin/bash
pd_f=1.129
d_f=1.126
fr_numb=18
fr_numb=0
r_m=$(echo "scale=6; \
    $pd_f*$d_f * (1 / sqrt(3)) + \
    ($fr_numb - 1) * ( \
        $pd_f * $d_f * (1 / sqrt(3)) + \
        $pd_f * $d_f * 0.5 * \
        ( \
            s(3.14159265 * 30 / 180) / c(3.14159265 * 30 / 180) \
        ) \
     ) + \
     0.4 " | bc -l)

Кстати, когда публикуете вопрос, публикуйте назначения переменных, чтобы их можно было легко скопировать, чтобы можно было воспроизвести вашу настройку, а не в стиле прозы, например "($pd_f и $d_f были объявлены 1.129 и 1.126 соответственно раньше, ох и $fr_numb =18)", который требует серьезного редактирования, чтобы сделать его пригодным для использования.

person Dennis Williamson    schedule 19.02.2011
comment
Спасибо за такие советы, постараюсь придерживаться. - person kasper; 19.02.2011

Если в вашей оболочке установлены 3 переменные, например:

pd_f=1
d_f=2
fr_numb=3

и вы запускаете исходную команду:

set r_m=`echo "scale=6; $pd_f*$d_f*(1/sqrt(3))+($fr_numb-1)*($pd_f*$d_f*(1/sqrt(3))+$pd_f*$d_f*0.5*(s(3.14159265*30/180)/c(3.14159265*30/180)))+0.4"|bc -l`

тогда вы получите $1, установленный на r_m=5.018798 (и все другие позиционные параметры не определены). Это связано с тем, что в bash и всех других производных от оболочки Bourne оператор set используется для настройки параметров оболочки или для установки значений позиционных параметров, $1, $2, ... и т. д. (но не $0).

Если у вас нет значений для трех переменных, вы получаете синтаксические ошибки, диагностируемые bc.

Обратите внимание, что исходная команда не устанавливает переменную r_m; это установит переменную только в оболочке C или производной оболочке C. Оператор set совершенно не влияет на переменную оболочки $r_m. То, что вы увидели в результате в $r_m, было тем, что осталось в переменной от вашего предыдущего эксперимента.

С другой стороны, когда вы запускаете:

r_m=`echo "scale=6; $pd_f*$d_f*(1/sqrt(3))+($fr_numb-1)*($pd_f*$d_f*(1/sqrt(3))+$pd_f*$d_f*0.5*(s(3.14159265*30/180)/c(3.14159265*30/180)))+0.4"|bc -l`

то вы назначаете переменной r_m.

person Jonathan Leffler    schedule 19.02.2011

заключите свою команду в $()

r_m=$(echo "scale=6; $pd_f*$d_f*(1/sqrt(3))+($fr_numb-1)*($pd_f*$d_f*(1/sqrt(3))+$pd_f*$d_f*0.5*(s(3.14159265*30/180)/c(3.14159265*30/180)))+0.4"|bc -l)
person kurumi    schedule 19.02.2011
comment
ну, правда в том, что он заключен в ``, но я не знал, как вставлять обратные кавычки в кавычки. $() не помогло. - person kasper; 19.02.2011
comment
$() проще вводить (и показывать) здесь, в Stackoverflow, что является причиной его использования. Другая причина заключается в том, что легче увидеть вложенность, когда у вас более одного уровня. Однако это ничего не делает для вашей проблемы. - person Paŭlo Ebermann; 19.02.2011