第 8 回 繰り返し、配列

本日の内容


8-1. 前回の復習---二次方程式の解法(演習7-6)

判別式 D=b*b-4*a*c が 0 より大きい場合
解は二つの実数になるので、次の値を計算するだけです。
      -b + √D
x1 = ----------
        2a

      -b - √D
x2 = ----------
        2a

2x2-5x-3=0 の解は D=(-5)2-4*2*(-3)=1 より、

     5+√1
x = ---------
      2*2

      5+1
  = -------
       4

       3
  =  ----
       2

または
     5-√1
x = -------
     2*2

      5-1
  = -------
       4

  = 1
D=0 の時
解は一つの実数だけなので次の値を計算するだけです。
     -b
x = ----
     2a

例えば x2+2x+1=0 の解は D=22-4*1*1=0 より、

   -2±√0
x= ---------
    2*1

     -2
  = ----
      2
             
  =  -1
D が負の場合
解は二つとも複素数になります。√D が虚数になるので、実部と虚部はそれぞれ次 のようになります。

       -b
実部 = ----
       2a

        √(-D)
虚部 = --------
          2a

例えば x2-2x+5=0 の解は D=(-2)2-4*1*5=-16 より、

     2 + √(-16)
x = ------------
      2*1
     2 ± 4√-1
  = ------------
         2
             
  =  1 ± 2i

C言語では複素数をそのままでは扱えないので、実部(-b/(2*a))と虚部(√ (-D)/(2*a))をそれぞれ求めてから、「実部 ± 虚部 i」と表示するしかあり ません。

8-2. Circuit Maker

電気回路

演習8-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」を選ぶと画面に合成抵抗値が表示されます。

演習8-2

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

ヒント

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


電子回路

演習8-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. グラフの右側にカーソルがありますので、それを移動してグラフの値を読みと り、出力電位差を計測します。

演習8-4

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


参考文献

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

ディジタル回路

演習8-5

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

xyz1z0
0000
0101
1001
1110
ヒント
  1. 半加算器の回路は次のようになります。
  2. (Digital, Gates, 2-In AND) と (Digital, 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」を選びます。 スイッチを入り切りすると、それに応じてスイッチの値の和に対応するランプ が光ります。

演習8-6

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

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

8-3. 漸化式と繰り返し

漸化式

数学では、数の列に対して、添字に番号をつけた文字を割り当てます。 例

a0=0,
a1=1, 
a2=2, 
a3=3, 
a4=4, 
a5=5,
...

これに対して、0 番目の値、 1 番目の値と、全ての値を具体的に指定せず、 i番目の値を i を使用して表すことがあります。 このような表し方を一般項と言います。 上の例だと、一般項はai=i となります。

演習8-7

次の数列の一般項を求めなさい。

  1. b0=2, b1=4, b2=6, b3=8, b4=10, ...
  2. c0=1, c1=3, c2=5, c3=7, c4=9, ...
  3. d0=10, d1=9, d2=8, d3=7, d4=6, ...

数列の別の定義として、 「a0の値」と、 「ai+1の値を aiを使った式」で定義するという方法があ ります。 この式を漸化式と言います。 また、漸化式から一般項を求めることを「漸化式を解く」と言います。

例:
  a0=0
  ai+1=ai+1

この場合、この漸化式を解くと ai=i となります。 なお、 プログラミングでは逆に一般項から漸化式を導くことをすることがあり ます。

演習8-8

次の漸化式を解きなさい(数学的な解法で解く必要はない。数列をいくつか書 き出してみて一般項を予想するだけで良い)。

  1.   a0=2
      ai+1=ai+2
    
  2.   a0=1
      ai+1=ai+2
    
  3.   a0=10
      ai+1=ai-1
    
  4.   a0=1
      ai+1=ai×2
    

演習8-9

次の数列の漸化式を求めなさい。

  1. b0=2, b1=4, b2=6, b3=8, b4=10, ...
  2. c0=1, c1=3, c2=5, c3=7, c4=9, ...
  3. d0=10, d1=9, d2=8, d3=7, d4=6, ...

a0+ a1+ ...+ an-1 を次のように表します。

n-1
 Σ ai
i=0

Σの中には一般項を書き、下には添字の始めの値、上には最後の値を書きます。 例えば 1 + 3 + 5 + ... + 99 は次のように書きます。

 49
 Σ (2i+1)
i=0

但し、(添字、開始時の値、終了時の値)が(i,1,n)な ど明らかな時、Σ ai などと省 略して書く場合があります。 また次の漸化式が成り立ちます。

n+1
 Σ ai = a0+a1+...+an+an+1
i=0

         n
       = Σ ai + an+1
        i=0

つまり、第 n 項までの和を Sn で表すと次の漸化式が成り立ちます。

S0  = a0
Sn+1 = Sn+an+1

繰り返し

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

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

条件式が正しい限り繰返し文を実行し続けます。 一方、始めに条件式が成立しなければ繰返し文は一回も実行されません。 条件式が成立すると繰返し文が実行されますが、もし繰返しているうちに条件 式が変わらないと永遠に繰り返しが起きてしまいます。 繰り返しの基本的なテクニックとして、次のような変数を使用します。

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

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

演習8-10

次のプログラムを走らせなさい。 また、このプログラムを改造して 「●」を 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 になります。

演習8-11

下のプログラムを走らせなさい。 また、演習8-9の答えを参考にして、このプログラムを改造し、ループ変 数の値が以下のようになるようにしなさい。

  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;
  }
}

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

演習8-12

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

  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");
}

演習8-13

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

#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 の値を更新する */
  }
}

演習8-14

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

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

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

演習8-15

画面につぎのようなパターンを出力するプログラムを作りなさい。

●
●●
●●●
●●●●
●●●●●
●●●●●●

8-4. 配列

宣言文での初期化

C 言語では宣言文で変数の値を代入(初期化)できます。

int i=0;
float a=2.3;
char d='F';

配列

C 言語で数列を取り扱うために配列という概念が用意されています。 添字は角括弧「[ ]」で括ります。 つまり、a0, a1, a2 はそれぞれ a[0], a[1], a[2] と表します。 aiは a[i] と表します。 ただし、添字に使用できる変数は整数型(int)だけです。 さらに添字には a[i+1] や b[j*2] など、整数を値に持つ式を書くことができます。

配列を使う時、宣言は次のようにします。

int a[5];
char b[3];
float c[4];

するとそれぞれ、次の変数が使えるようになります。

a[0], a[1], a[2], a[3], a[4]
b[0], b[1], b[2]
c[0], c[1], c[2], c[3]

プログラムでは、配列はそれぞれ普通の変数として使用することができます。 但し、実行中に配列の値をまとめて代入することはできません。 一方、初期化する際には次のようにまとめて値をセットできます。

int a[5]={ 3, 4, 6, 0, -1 };

このようにすると 次のように値が代入されます。

a[0]= 3,
a[1]= 4,
a[2]= 6,
a[3]= 0,
a[4]=-1

さらに値をまとめてセットする場合、要素数の指定を省略することができます。

float b[]={ 1.3, -3e-2, -5.0 };

このようにすると次のように値が代入されます。

b[0]= 1.3,
b[1]=-3e-2,
b[2]=-5.0

演習8-16

次のプログラムを完成させなさい。また、改造して平均値も出力するようにし なさい(#define X Y はプログラム中で Y を X という 名前で使うことを意味する)。

#include <stdio.h>
#define N 5
main(){
  int i;
  float a[N]={2.3, 4.4, 3.9, -1.2, 0.3};
  float s;
  i=0;
  s=0;
  while(i<N){
    printf("a[%1d]=%f\n",i,a[i]);
    /* s に a[i] を加える */
  }
  printf("合計: %f\n",s);
}

演習8-17

以下の数の標準偏差を求めなさい。 但し標準偏差は次の式で与えられる。

標準偏差 = √分散

       Σ(素点 - 平均)2
分散 = ----------------
               n
3.5, 2.0, 5.5, 2.3
ヒント

分散は次の式を使うと while 文一つで求めることができる。


       Σ(素点 - 平均)2
分散 = ----------------
               n

        Σ((素点)2 - 2×素点×平均 + (平均)2)
     = -----------------------------------
                      n

        Σ(素点)2            Σ素点             Σ 1	
     = --------- - 2×平均×-------- +(平均)2×------
           n                   n                n

     = ((素点)2 の平均) - (平均)2

演習8-18

以下の数の偏差値を求めなさい。 但し偏差値は次の式で与えられる。

          (素点 - 平均)
偏差値 = --------------- × 10 + 50
             標準偏差
3.5, 2.0, 5.5, 2.3

演習8-19

以下の数のペア(xi, yi)が、方程式 y= ax+b をほぼ満たす関係がある時、この a, b の値を最小二乗法を 使って求めなさい。

(2.3, 4.5), (1.1, 2.4), (5.5, 10.9), (4.9, 10.0)
ヒント

最小二乗法によると、 a と b は次の連立方程式を満たす。

xi2) a + (Σxi) b = Σ(xiyi)
(Σxi)  a +     n b = Σyi

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