Masalah bc tentang ekspresi panjang

3

Saya ingin menghitung ekspresi dalam shell. Saya menggunakan kode berikut:

pi=$(echo "scale=10; 4*a(1)" | bc -l)
i=3
d=`expr (1+c($pi*($i/10)+$pi))/2 | bc -l`

Tapi katanya

bad pattern: (1+c(3.1415926532*(3/10)+3.1415926532))/2

Mengapa?

yuxuan
sumber

Jawaban:

3

Karena Anda menggunakan exprdalam perintah terakhir Anda di mana Anda mungkin harus menggunakan echo.

PS Saya menyarankan Anda untuk menggunakan $(…)formulir di kedua bcperintah (bukan `…`).

G-Man
sumber
1
Ungkapan ini juga perlu dikutip untuk mencegah shell mencoba mengurai tanda kurung
roaima
1

Waspadalah bahwa di mana Anda mengatur skala memiliki pengaruh pada perhitungan.

Skrip ini:

bc -l << \EOF
scale = 10
pi = 4 * a(1)
i = 3
(1 + c(pi * (i / 10) + pi)) / 2
EOF

bc -l << \EOF
pi = 4 * a(1)
i = 3
scale = 10
(1 + c(pi * (i / 10) + pi)) / 2
EOF

bc -l << \EOF
pi = 4 * a(1)
i = 3
r = (1 + c(pi * (i / 10) + pi)) / 2
scale = 10
r/1
EOF

bc -l << \EOF
scale = 100
pi = 4 * a(1)
i = 3
r = (1 + c(pi * (i / 10) + pi)) / 2
scale = 15
r/1
EOF

output:

.2061073736
.2061073739
.2061073738
.206107373853763
Stéphane Chazelas
sumber
1

Jika Anda mengikuti saran saya, Anda tidak akan menggunakan `` atau $()- ini sedikit konyol. bcadalah interpreter interaktif yang berorientasi garis. Bunyinya dalam baris dari stdin, memeriksa apakah perlu yang lain berdasarkan input yang baru saja dibaca, dan kemudian mencetak hasilnya ke stdout atau meminta lebih banyak pada stdin. Seperti shell Anda, itu bahkan akan menolak untuk melakukan apa pun lebih dari output line-buffer bahkan ketika ditulis ke selain terminal. Tidak perlu sama sekali untuk memanggil yang baru bcuntuk setiap perhitungan - terutama dalam substitusi perintah yang juga melibatkan memanggil shell baru dan mengalokasikan pipa baru.

Cara terbaik adalah mengatur proses bersama.

# in a bash shell
exec 8<> >( : ) 9< <( bc <&8 )
echo 'b=5;++b' >&8
read  b <&9
echo "$b"

6

Dan bcitu hanya akan terus berjalan - semua nilai variabel yang Anda lakukan begitu banyak pekerjaan untuk bolak-balik di antara sesaat, bcproses yang diganti perintah bisa lebih mudah disimpan secara terpusat di pusat bc.

echo b\*b >&8; read b <&9; echo "$b"

32

Dan bahkan lebih baik, karena saya belajar bagaimana melakukan ini beberapa hari yang lalu, Anda dapat menempatkan bcproses pada server soket.

{ ncat -l 9000 --allow localhost -k| bc; } <>/dev/fd/1 |:&

Dan dengan shell yang berbicara /dev/tcpbahasa:

{ echo 'b=10;b' >&0; read b; echo "$b"; } <>/dev/tcp/localhost/9000

10

Itu bisa menjadi sedikit rumit. Saya menulis sebuah fungsi kecil yang dipanggil bchat()untuk membuatnya lebih mudah.

bchat(){
        local IFS=\;                                 ### separate on ;
        printf ${1+'%s;"\n"\n';}"$*"                 ### print \0 if no args
        set --                                       ### init  args
        while  read   bchat       &&                 ### while read <bc
              "${bchat:+set}" -- "$@" "${bchat:=$*}" ### append to args
        do :;  done 2>/dev/null                      ### and done
}       <>"$BC" >&0                                  ### $BC must be set

Setelah menyiapkan server soket seperti yang ditunjukkan di atas, Anda mungkin menggunakan fungsi itu seperti:

BC=/dev/tcp/localhost/9000
bchat b=5 x='(b--)' '"x="' ++x '"b="' --b
echo "$bchat" 

x=6;b=3

... dan lagi, keadaan itu akan bertahan selama proses bc tidak ...

mikeserv
sumber