Melakukan matematika sederhana di baris perintah menggunakan fungsi bash: $ 1 dibagi dengan $ 2 (mungkin menggunakan bc)

33

Kadang-kadang saya perlu membagi satu nomor dengan yang lain. Akan lebih bagus jika saya bisa mendefinisikan fungsi bash untuk ini. Sejauh ini, saya terpaksa menggunakan ekspresi seperti

echo 'scale=25;65320/670' | bc

tetapi akan lebih bagus jika saya bisa mendefinisikan fungsi .bashrc yang terlihat seperti

divide () {
  bc -d $1 / $2
}
ixtmixilix
sumber

Jawaban:

45

Saya memiliki fungsi bash praktis bernama calc:

calc () {
    bc -l <<< "$@"
}

Contoh penggunaan:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Anda dapat mengubahnya sesuai keinginan Anda. Sebagai contoh:

divide() {
    bc -l <<< "$1/$2"
}

Catatan: <<< adalah string di sini yang dimasukkan ke dalam stdin dari bc. Anda tidak perlu memohon echo.

dogbane
sumber
3
Saya setuju ini terlihat lebih baik tanpa tambahan gema yang dilemparkan, tetapi karena itu adalah shell builtin, ia datang dengan sedikit atau tanpa biaya tambahan. Apa yang membuat saya tidak menggunakan '<<<' dalam fungsi shell adalah keterbatasannya untuk bash, sementara gema tambahan memungkinkan menggunakannya di shell bourne asli atau ksh tanpa perubahan.
Tatjana Heuser
@TatjanaHeuser ksh, varian 93, mendukung string di sini.
Kusalananda
Untuk menetapkan ke variabel, saya melakukan ini: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski
20

Bash dapat melakukan matematika itu sendiri sampai batas tertentu. Namun, ini tidak berguna untuk keakuratan.

[user]$ echo $(( 10/5 ))
2

Tapi Anda benar - fungsi bash akan menjadi jalan pintas sederhana dan contoh Anda pada dasarnya berfungsi.

divide() {
  echo "scale=25;$1/$2" | bc
}

Lemparkan ke dalam .bashrc Anda dan kemudian Anda dapat:

[user]$ divide 10 5
2.0000000000000000000000000
rewew
sumber
1
echo $((10 / 5))tidak perlu kutip.
pengguna tidak diketahui
1
Gangguan yang signifikan: echo $((6383/7671)) akan memberi Anda nol. Anda harus eksplisit tentang nomor floating point:echo $((6383.0/7671.0))
Sridhar Sarnobat
9

Anda mungkin tahu bash builtin 'expr' seperti pada

$ expr 60 / 5
12

yang terbatas pada bilangan bulat dan membutuhkan ruang di antara argumen.

Apa yang membuat Anda tidak mendefinisikan fungsi di sepanjang garis ekspresi gema yang sudah Anda gunakan? Yaitu

 divide () {
   echo $1/$2 | bc
 }
Tatjana Heuser
sumber
1
hanya ketidaktahuan. saya tidak menyadari bahwa saya bisa membuatnya bekerja seperti itu ...
ixtmixilix
7

Tidak benar-benar jawaban untuk pertanyaan yang tepat ini, tetapi mungkin baik untuk diketahui. Gunakan zsh;-)

% echo $((65320./670))
97.492537313432834
Stéphane Gimenez
sumber
Saya sebenarnya mencari pertanyaan ini karena saya berganti ke zsh dan tidak bisa menggunakan bash's exprbuiltin, jawaban yang sangat bagus terlepas dari itu :)
Steen Schütt
2

Jika Anda telah calcmenginstal pada sistem Anda dan Anda tidak suka pembulatan, Anda dapat:

div() { calc "$1 / $2"; }

sumber
hmm ... tidak dapat menemukan paket debian untuk 'calc'
ixtmixilix
Paket ini disebut apcalc (Presisi Arbiter) ... Biner disebutcalc
Peter.O
@ Peter.O Ok, dalam repo Arch Linux namanya calc.
2

Retasan kotor untuk nilai-nilai kecil dan presisi terbatas tanpa menggunakan bc akan, untuk melipatgandakan nominator sebelum pembagian, untuk mendapatkan hasil yang akurat.

Contoh tanpa presisi:

echo $((13/7)) 
1

dan dengan presisi 2 digit: kalikan dengan 100 dan pindahkan titik desimal 2 langkah ke kiri:

echo $((100*13/7)) | sed 's/..$/.&/'
1.85
echo $((100*13/7))%
185%

Ini hanya berguna jika rentang angka diketahui sebelumnya, dan presisi selalu sama. Menghindari menelepon bc , dan menelepon sed sepertinya tidak masuk akal.

Perhatikan, bahwa mengalikan nilai mungkin menyebabkan kesalahan overflow, tetapi tidak terlalu awal:

echo $((1000000000*12345678901))
-6101065172709551616
Pengguna tidak diketahui
sumber
Menggunakan tanda kurung ganda untuk mengevaluasi ekspresi matematika sudah usang. Gunakan: $[expression]sebagai gantinya
laebshade
3
@laebshade: Saya bisa membuktikan Anda salah, yang terjadi adalah sebaliknya. Berikut ini adalah kutipan dari manual bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
pengguna tidak diketahui
Juga dibahas di sini , di  sini  dan di  sini .
G-Man Mengatakan 'Reinstate Monica'
0

Alih-alih menggunakan bc, Anda bisa menggunakan awk:

div() { awk -v p=$1 -v q=$2 'BEGIN{print p/q}'; }
jfg956
sumber
-4
echo Division
efgh=$num1/$num2
remainder=$num1%num2
echo $num1 "/" $num2 "=" $efgh.$remainder
echo
Boomer
sumber