せっかくラズパイを購入したので、電子工作もしていきますが、まずは電子回路の基礎オームの法則の勉強から始めます。
電圧(E) = 抵抗(R) x 電流(I)
電圧値5Vで、抵抗値が100kΩなら、電流値は、
5 ÷ 100000 = 0.00005 (5マイクロA)
上図のように、抵抗を直列に繋げるとき、抵抗値は、R1+R2となります。
一方、並列に繋げると、抵抗値は、1/(1/R1 + 1/R2) となります。複雑ですね。今回のコマンドラインの主題は、この分数計算となります。
コマンドラインで分数は使えるのでしょうか。例えば、pythonで1(被除数)÷3(除数)を求めようとした場合、
~$ python >>> 1 / 3 0
なんてことでしょう。答えが0になりました。たいていのプログラミング言語は、このように整数どうしの割り算は、結果が切り捨てされます。
小数点以下を求めたい場合は、被除数また除数を浮動小数点数で表現します。
~$ python >>> 1.0 / 3 0.3333333333333333 >>> ~$ irb irb(main):001:0> 1/3 => 0 irb(main):002:0> 1.0/3 => 0.3333333333333333 irb(main):003:0>
浮動小数点数を使った計算は、精度の問題があります。下記では1を49で割って49で掛けただけなので、数は1のまま変わらないはずですが、結果は1になっていません。
~$ irb >>> 1.0/49*49 0.9999999999999999 >>>
まあ、実際抵抗値の計算では、そこまでの精度は不要かと思いますが、分数計算したい場合、LISP系言語が便利です。
LISP(scheme系)言語Gauche(ゴーシュ)を使ってみましょう。インストールはDebianではsudo apt-get install gauche。Gaucheシェルの実行はgoshを実行します。
~$ gosh gosh> (+ 1 2) 3
1 + 2を計算してみました。
ん? よくわからない。それはそのはずです。LISPの式は学校で習った足し算の書き方と大きく異なります。
まず括弧。LISP言語のプログラムはかならず括弧がつきます。括弧は、リストを表します。
(要素1 要素2 要素3 要素4 … )
リストは上記のような構成ですが、要素1に、命令を書きます。 上記コマンドラインの例で足し算”+”の部分です。
余談ですが、私はキー入力する際、シフトキーが必要になるため()がとても疎ましく思えますが、LISPの()で囲む言語仕様自体はものすごく美しいと感じています。
引き算をしてみましょう。
gosh> (- 5 2) 3
リストなので、数をたくさん扱えます。
gosh> (+ 1 2 3 4 5 6 7 8 9 10) 55 gosh> (- 1 2 3 4 5 6 7 8 9 10) -53
さて、割り算をしてみましょう。
gosh> (/ 1 3) 1/3
結果は、1/3 つまり3分の1、分数がそのまま出ました。分数となるため、浮動小数点数計算のように精度落ちがありません。
1 ÷ 49 × 49 を計算してみましょう。
gosh> (* (/ 1 49) 49) 1 gosh>
一致しました。
もちろんgoshでも浮動小数点数が使えるので、以下のように不一致となります。
gosh> (* (/ 1.0 49) 49) 0.9999999999999999 gosh>
では抵抗の計算に戻ります。並列接続の時、計算式は、
1/(1/R1 + 1/R2)
でした。
R1=20、R2=30として、goshで計算すると、
gosh> (/ 1 (+ (/ 1 20) (/ 1 30))) 12 gosh>
では、これをbash関数にして、R1、R2を引数指定できるようにしてみます。
~$ resister(){ gosh -E"print (/ 1 (+ (/ 1 $1) (/ 1 $2)))" -Eexit }
gosh の-Eオプションは一番外側の()を内部でつけてくれます。
-Eexitは、exitをしないとgoshシェルから抜けないので必要になります。
確認してましょう。
~$ resister 20 30 12 ~$ resister 20 20 12 ~$ resister 15 16 240/31
結果が分数で出てしまいました。途中計算は分数で良いのですが、最終結果は小数点で表現したいので、少し改造します。
~$ resister(){ gosh -E"print (/ 1.0 (+ (/ 1 $1) (/ 1 $2)))" -Eexit }
1を1.0に変えただけです。再度確認してみます。
~$ resister 15 16 7.741935483870967 ~$ resister 100 30 23.076923076923077 ~$ resister 20 30 12.0 ~$ resister 20 20 10.0 ~$
コメント