第 9 回 回路シミュレータ, 繰り返し文

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

9-1. Circuit Maker

電気回路

演習9-1

次の合成抵抗を求めなさい。
ヒント
  1. 「Devices→Browse... x」 で部品の一覧を表示する画面にし、 Major Device Class から Resistors を選択します。 Minor Device Class から Resistors を選択します。 Device Symbol から Resistor を選択します。 (以後、この操作を Major Device Class, Minor Device Class, Device Symbol の順に (Resistors, Resistors, Resistor)と書きます)
    部品の選択画面

    「Place」ボタンを押すと、作業領域に画面が切り替わります。 白い画面の中央付近を左クリックすると、抵抗を表す記号が表示されます。

    抵抗

    抵抗の記号を指して右クリックして「Duplicate」を選択する。 そして合計 3 本の抵抗を配置します。 抵抗記号を右クリックして「Edit Device Data」を選びます。 「Label-Value」という欄が抵抗値を表しますので、ここで抵抗値を指定しま す。

  2. 部品表から (Analog, Instruments, Multimeter) を選び 「Place」ボ タンを選び適当な位置で左クリックします。 すると、メータの種類を聞く画面が出るので、「Ohms」を選択し、「Ok」を押 す。

    メータ選択図
  3. シミュレーションの都合上、基準となる 0 V の点が必要なので、(Analog, Power, Ground) を配置します。
  4. 「Options→Arrow/Wire」を選び、部品の端同士を結び、回路を完成させます。 完成図は次のようになります。
    完成図
  5. 「Simulation」を押して、 「Analog Mode」と表示されていることを確認します。 もし、「Digital Mode」が表示されている時は、この「Digital Mode」を選択 すると「Analog Mode」になります。
  6. 「Simulation → Run」を選ぶと画面に合成抵抗値が表示されます。

演習9-2

下の回路図で1Ωの抵抗を流れる電流の大きさを求めなさい。

ヒント

電池は(Anarog, Power, Battery)。 電流を測定するにはマルチメータで current を指定します。 完成図は次のようになります。


電子回路

演習9-3

下の回路図で、A 点と B 点の電圧を調べ、増幅率を求めなさい。

ヒント
  1. 部品を配置して回路図を作成します。 トランジスタは(Transistors, BJTs, NPN TransB) を選び、下のモデル選択画 面から「2N2222A」を選びます。

    1kHz を入力するには、(Analog, Instruments, Signal Gen) を選びます。 電圧の幅を入力するには、Signal Gen の記号を右クリックし、「Edit Signal Generator」を選びます。そして、「Peak Amplitude」の欄に 100mV を入力します。

  2. 「Simulation → Run」を選び、シミュレーションを開始します。
  3. 電圧を測りたい点を左クリックすると、画面下に観測された値がグラフで 表示されます。 別の点を「Shift」キーを押しながら左クリックすると、グラフが重なって表 示されます。
  4. グラフの右側にカーソルがありますので、それを移動してグラフの値を読みと り、出力電位差を計測します。

演習9-4

下の回路図で、A 点と B 点の電圧を調べ、増幅率を求めなさい。


参考文献

鈴木雅臣「実験研究 トランジスタ回路の誕生」トラ技ORIGINAL No.1. CQ出版 (1989)

ディジタル回路

演習9-5

二進数一桁(つまり 0 か 1)を二つ入力して、足し算を実現するディジタル 回路を作りなさい。 但し、真理値表は次のとおりです。

xyz1z0
0000
0101
1001
1110
ヒント
  1. 半加算器の回路は次のようになります。 (x,y)が (0,1) か (1,0) の時に 1、 (0,0) か (1,1) の時に 0 になる論理演算を EX-OR(Exclusive OR, X-OR, 排他的論理和)と言います。
  2. (Digital Basics, Gates, 2-In AND) と (Digital Basics, Gates, 2-In XOR) を配置します。 出力に (Digital Animated, Displays, Logic Display) を二つ、入力用に (Digital, Power, Logic Switch) を二つ配置します。
  3. 回路を配線します。完成図は次のようになります。
  4. 「Simulation」を押して、 「Digital Mode」と表示されていることを確認します。 もし、「Analog Mode」が表示されている時は、この「Analog Mode」を選択 すると「Digital Mode」になります。
  5. 「Simulation → Run」を選びます。 スイッチを入り切りすると、それに応じてスイッチの値の和に対応するランプ が光ります。

演習9-6

以下に示す全加算器を利用して、二進数二桁を二つ入力する足し算回路を作り なさい。 全加算器とは 3 つの一桁の二進数の入力の和を二桁の二進数として出力する ものです。

真理値表は次のとおりです。

xycz1z0
00000
01001
10001
11010
00101
01110
10110
11111
ヒント
  1. 筆算と同じ要領で下の桁から順に足していきます。 その時繰り上がりの処理もします。 つまり、次のような回路を作ることになります。
    足し算器の概念図
  2. 最下位桁は半加算器で計算します。 そして、下の桁の繰り上がりと、その桁の二つの数の合わせて三つの数の足し 算を全加算器で行います。
  3. 表示に Logic Display を使う代わりに、 (Digital Animated, Displays, Hex Display) も使えます。

9-2. 繰り返し

while文

C 言語でもっとも基本的な繰り返し文は while 文です。 while 文は次のような構文になっていて、 if 文とよく似ています。

while(条件式){
  繰り返し文
}

条件式が正しい限り繰返し文を実行し続けます。 一方、始めに条件式が成立しなければ繰返し文は一回も実行されません。 条件式が成立すると繰返し文が実行されますが、もし繰返しているうちに条件 式が変わらないと永遠に繰り返しが起きてしまいます。 if 文と違う点は、 if 文では条件文の中身を変化させることに意識をする必 要がないのにもかかわらず、 while 文では条件式を繰り返している間中見て いて、繰り返している間は常に成立し、繰り返しを終える時に条件が不成立に なるようにしなければならないことです。 そこで、繰り返しの基本的なテクニックとして、次のような変数を使用します。

  1. 条件式の中に現れる。
  2. 繰返し文の中で値が変更される。

このような変数のことをループ変数と言います。

例えば、 5 回だけ繰り返すことを考えます。その時、ループ変数の役割は、 繰り返しの回数を数えることです。 そのためには、繰り返しの中で繰り返されるたびにループ変数が 1 ずつ増え る必要があります。 これには次の式を使います。

ループ変数 = ループ変数 + 1;

このようにするとこの式を実行した回数だけループ変数が増えます。 これを利用して、while 文に入る前にループ変数の初期値を与え、 while 文 の条件式でループ変数の値を監視するようにすると、 5 回処理を繰り返すこ とができるようになります。

ループ変数 = 1;
while(ループ変数 <= 5){
  処理;
  ループ変数 = ループ変数 +1;
}

これを実行すると、次のようになります。

  1. ループ変数 = 1
  2. while 条件成立
  3. 処理
  4. ループ変数 = 1+1 = 2
  5. while 条件成立
  6. 処理
  7. ループ変数 = 2+1 = 3
  8. while 条件成立
  9. 処理
  10. ループ変数 = 3+1 = 4
  11. while 条件成立
  12. 処理
  13. ループ変数 = 4+1 = 5
  14. while 条件成立
  15. 処理
  16. ループ変数 = 5+1 = 6
  17. while 条件不成立
  18. 終了

これにより処理が 5 回行われたことがわかると思います。

演習9-7

次のプログラムを走らせなさい。 また、このプログラムを改造して 「●」を 10 個表示するプログラムを作り なさい。

#include <stdio.h>
main(){
  int a;
  a=0;
  while(a<5){
    printf("○");
    a=a+1;
  }
  printf("\n");
}

「a=a+1」という記法は、「次の a は、今の a に 1 を足したもの」という意味 になります。つまりこれは漸化式 ai+1=ai+1 と同じ役割になります。 始めに「a=0」としておいて、「a=a+1」を繰り返すと、「a=a+1」を繰り返した回数 だけ a が増えていきます。繰り返し回数を i とすると、 a の値は i になります。

演習9-8

下のプログラムを走らせなさい。 また、このプログラムを改造し、ループ変 数の値が以下のようになるようにしなさい。

  1. 1, 3, 5, 7, 9
  2. 10, 9, 8, 7, 6
#include <stdio.h>
main(){
  int b;
  b=2;
  while(b<=10){
    printf("ループ変数 = %d\n",b);
    b=b+2;
  }
}

一方、ループ変数を使用して数列の一般項を書くと、数列を表示するこ とができます。

演習9-9

下のプログラムを走らせなさい。 また、このプログラムを改造して、次を表示するようにしなさい(余裕のある 人は最後のカンマ「,」が出ないようにしなさい)。

  1. 1, 3, 5, 7, 9, ... 19
  2. 10, 9, 8, ... , -10
  3. 1, 2, 4, 8, 16, ... 1024
#include <stdio.h>
main(){
  int i,b;
  i=0;
  while(i<10){
    b=2*(i+1);
    printf("%d, ",b);
    i=i+1;
  }
  printf("\n");
}

演習9-10

以下の三角関数の表を出力するプログラムを完成させなさい。

#include <stdio.h>
#include <math.h>
main(){
  int i;
  float x,y;
  i=0;
  while(i<20){
    x = /* x の値は 0 から 2πの間 をとるようにする。 */
    y = /* sin x の値を入れる */
    printf("x=%f, sin(x)=%f\n",x,y)
    /* i の値を更新する */
  }
}

演習9-11

フィボナッチ数列を(20個)表示するプログラムを書きなさい。 但し、フィボナッチ数列とは次のような数列である。

1, 1, 2, 3, 5, 8, 13, 21, 34, 53, ...

a0=1
a1=1
ai=ai-1+ai-2 (i≧2)

C 言語の独特の記法(1)式の値

C 言語では全ての文や式に値を持ちます。 例えば代入文は代入した数を値に持ちます。 j=0 という代入文の値は 0 です。 従って次のような記法が可能です(代入文は右から処理されます)。

i=j=0

この場合、「j=0」 により j に 0 が代入されますが、「j=0」の式の値は 0 なので、 i にはこの式の値 0 が代入されます。

条件文の式の値は、真であれば 1、偽であれば 0 です。従って、0==0 は 1、 1==0 は 0 の値を持ちます。一方、条件文では、 0 なら偽、0 以外の値なら 真だと判定します。したがって、次の文は同じ意味を持ちます。

if(x!=0){}
if(x){}

演習9-12

次の操作で変数 i,j の値はどうなっているか?

  1. i=(j=1)+1;
  2. i=((j=0)==0);
  3. if(i){i=0;}

C 言語の独特の記法(2)代入演算子

プログラミングでは i=i+1 など、もともと変数に入っている値を 「増やす」など変化させる操作が 多いです。そのため、これを i+=1 と書くこともできるようになってます。 これを代入演算子と言います。 また、特に 1 を足したり引いたりすることが多いので、特別に 1 増やすのを ++i、 1 減らすのを --i と書くことができます。 これらのそれぞれの式の値は、計算結果の変数の値になります。 一方で、i++, i-- は変数の値を1 増やしたり減らしたり する際に、式の値は増減させる前の変数の値になります。 また、 2 減らすのは i-=2、 5 倍するには i*=5 と書きます。

演習9-13

次のプログラムを実行し、実際に式の値を調べなさい。

#include <stdio.h>
main(){
  int i,j;
  printf("i=0 で i に 1 を増やす\n");
  i=0;j=(i=i+1);printf("i の値 %d, 式の値 %d\n",i,j);
  i=0;j=(i+=1);printf("i の値 %d, 式の値 %d\n",i,j);
  i=0;j=(++i);printf("i の値 %d, 式の値 %d\n",i,j);
  i=0;j=(i++);printf("i の値 %d, 式の値 %d\n",i,j);
}

i++ は配列変数の処理で使います。詳しくは次回以降に説明します。

演習9-14

次のプログラムで何が出力されるか予想しなさい。 また、画面に 10, 8, 6, 4, 2 と出力されるように改造しなさい。

#include <stdio.h>
main(){
  int i;
  i=5;
  while(i--){
    printf("%d\n",i);
  }
}

演習9-15

次のプログラムが何を出力するのか予想しなさい。 また、次のパターンを出力するよう、大幅に改造しなさい。

●
●●
●●●
●●●●
●●●●●
●●●●●●
#include <stdio.h>
main(){
  int i, j;
  i=5;
  while(j=i--){
    while(j--){
      printf("○");
    }
    printf("\n");
  }
}

for 文

他の言語では for 文は特別な動作をすることがありますが、 C 言語では for 文は while 文とほぼ同じです。 文法は次のようになります。

for(一番はじめにだけ実行する文 ; 条件文 ; 繰り返しの最後に実行する文 )
{ 繰り返しの内容}

つまり次の二つのプログラムは同じ意味になります。

  1. for(A;B;C){D;}
  2. A; while(B){D; C;}

実際には次のように使います。

for(i=0;i<10;++i){
  printf("%d\n",i);
}

これは次のプログラムと同じ意味です。

i=0;
while(i<10){
  printf("%d\n",i);
  ++i;
}

for 文で書くと、ループ変数の処理を一か所にまとめることができるので、繰 り返し回数が一目でわかるなどの利点があります。 逆に for の中にループ変数以外の文を多く入れてしまうと読みづらくなりま す。

演習9-16

次のプログラムの for 文を while 文に直しなさい。 また、n に 6, 14, 23 を入れて出力がどうなるか調べなさい。 なお、型が int 同士の割算は切捨てになります。 一方、a%b は a 割る b の余りを意味します。

#include <stdio.h>
main(){
  int n;
  n=11;
  for(;n;n/=2){
    printf("%d",n%2);
  }
  printf("\n");
}
参考

数を表す時、下の桁から表すのを little endian と言い、上の桁 から表すのを big endian と言います。 人間は通常 big endian で数を表現しますが、コンピュータでは little endian の方が処理に便利な場合もあり、使われることがあります。 Intel 社の Pentium Processor は little endian です。


演習9-17

次のプログラムの while 文を for 文に直しなさい。 また、 n の値を 32, 60 に変えて出力がどうなるか調べなさい。 余裕がある人は約数の数だけ表示するように改造しなさい。

#include <stdio.h>
main(){
  int n,i;
  n=18;
  printf("%dの約数は",n);
  i=1;
  while(i<=n){
    if(!(n%i)){
      printf(" %d",i);
    }
    i++;
  }
  printf("\n");
}

9-3. 宿題

Mupad をダウンロードしておいて下さい。


坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科