・p.185「フィボナッチ数列を求める」から
p.181 階乗を計算する(再掲載)
・階乗とは、ある正の整数において、その数から1までの全整数の積
※ 実質的にはその数から2までの全整数の積になる
・整数nの階乗を「n!」で表し、例えば、2!は2、3!は6、4!は24、5!は120、…
・これを逆順で展開すると
5! = 5×4×3×2×1
4! = 4×3×2×1
3! = 3×2×1
・なので、5!=5×4!、4!=4×3! であることから「n! = n×(n-1)!」が導ける。
・これをメソッドFactにすると、
int CalcFact(int n) { //nの階乗
return n * CalcFact(n - 1); //n×(n-1)!を返す(再帰する)
}
・これに、再帰の終了条件として「0の階乗は1」を加えると良い
int CalcFact(int n) { //nの階乗
return (n > 0) ? n * CalcFact(n - 1) : 1; //nが0超ならn×(n-1)!を返す(再帰する)でなければ1を返す
}
・p.182 fact01.csは上記を展開したメソッドになっている
提出フォロー:アレンジ演習:p.182 fact01.cs
・CalcFact(int n)メソッドを上記を用いてシンプルにしよう
作成例
//アレンジ演習:p.182 fact01.cs
using System;
class Fact {
public long CalcFact(int n) { //n!を返す
return (n > 0) ? n * CalcFact(n - 1) : 1; //nが0超ならn×(n-1)!を返す(再帰する)でなければ1を返す
}
}
class fact01 {
public static void Main() {
Fact f = new Fact();
for (int i = 0; i <= 20; i++) {
Console.WriteLine("{0}! = {1}", i, f.CalcFact(i));
}
}
}
p.185 フィボナッチ数列を求める
・フィボナッチ数列は統計やシミュレーションなどに用いる増加速度をもつ数字の並び。 ・先頭2値が1で、それ以降は前2値の和になる ・実例: 1,1,2,3,5,8,13,21,34,55,… ・よって、n番目のフィボナッチ数はn-1番目とn-2番目の和として、再帰で表現できる
p.185 fibonacci.cs
//p.185 fibonacci.cs
using System;
class fibo {
public long CalcFibo(int n) { //フィボナッチ数列のn番目を返す
long fb;
if (n == 1 || n == 2) { //先頭2要素は1固定(再帰の終了条件でもある)
fb = 1;
} else {
fb = CalcFibo(n - 1) + CalcFibo(n - 2); //3値目以降は前2値の和
}
return fb;
}
}
class fibonacci {
public static void Main() {
fibo f = new fibo();
for (int i = 1; i <= 30; i++) {
Console.WriteLine("f({0}) = {1}", i, f.CalcFibo(i));
}
}
}
アレンジ演習:p.185 fibonacci.cs
・条件演算子を用いて記述をシンプルにしよう
作成例
//アレンジ演習:p.185 fibonacci.cs
using System;
class fibo {
public long CalcFibo(int n) { //フィボナッチ数列のn番目を返す
return (n == 1 || n == 2) ? 1 : CalcFibo(n - 1) + CalcFibo(n - 2); //3値目以降は前2値の和
}
}
class fibonacci {
public static void Main() {
fibo f = new fibo();
for (int i = 1; i <= 30; i++) {
Console.WriteLine("f({0}) = {1}", i, f.CalcFibo(i));
}
}
}
p.188 refとout(値渡しと参照渡し)
・C#においてメソッドの引数は値渡しが基本であり、値のコピーが行われる ・よって、メソッド内で引数を変更しても、呼び出し側の指定した引数の値は変わらない ・p.189 swap01.csが失敗例で、Mainメソッドで定義して引数に指定しているxとyは、Swap関数の仮引数xとyとは(たとえ同名でも)無関係 ・C/C++では参照型の場合に参照渡しによりこれを解決できるが、C#では参照型でも値渡しになる ・なお、配列などのようにデータ構造を渡した場合は、構造の占有位置を示す値が値渡しされるので、受け取った側で同じオブジェクトを 用いるため、参照渡しになる
p.191 charngearray01.cs
//p.191 charngearray01.cs
using System;
class change {
public void modify(int[] array) { //引数が配列なので実質的に参照渡し
int n = array.Length; //要素数を得て
for (int i = 0; i < n; i++) { //全要素について繰返す
array[i] *= 2; //要素値を2倍にする
}
}
}
class changearray01 {
public static void Main(){
change c = new change();
int[] myarray = new int[3]{1, 2, 3};
Console.WriteLine("----modifyメソッド実行前----");
int i = 0;
foreach (int x in myarray) { //配列myarrayの全要素について繰返す
Console.WriteLine("myarray[{0}] = {1}", i, x); //値を表示
i++;
}
c.modify(myarray); //要素値を2倍にする
Console.WriteLine("----modifyメソッド実行後----");
i = 0;
foreach (int x in myarray) { //配列myarrayの全要素について繰返す
Console.WriteLine("myarray[{0}] = {1}", i, x);
i++;
}
}
}
p.192 refキーワード
・値渡しとなる引数と仮引数の両方に「ref」を前置すると、参照渡しに変更される ・なお、この引数は事前に初期化が必要だが、変数名は同じである必要はない
p.193 swap03.cs
//p.193 swap03.cs
using System;
class myclass {
private int temp;
public void swap(ref int x, ref int y) { //仮引数xとyは参照渡しにする
temp = x;
x = y; //ここでxを書き換えた結果が引数に反映する
y = temp; //ここでyを書き換えた結果が引数に反映する
}
}
class swap01 {
public static void Main() {
myclass s = new myclass();
int x = 10, y = 20; //引数用の変数を初期化
s.swap(ref x, ref y); //参照渡しにより、呼び出す
Console.WriteLine("x = {0}, y = {1}", x, y);
}
}
p.194(outキーワード)
※ テキストではrefの代わりに無条件にoutが利用できるような説明になっているが、制限もある ・refに代わりにoutを指定すると、事前の初期化が不要になる ・ただし、out指定の仮引数は初期化されていないことから、代入の右辺には記述できない ・よって、p.193 swap03.csの「ref」を「out」にするとエラーになる ・また、古いバージョンのC#では利用できない
p.194 outkeyword01.cs
//p.194 outkeyword01.cs
using System;
class MyClass{
public void Square(double x, double y, out double s) { //仮引数sは参照渡し
s = x * y; //よってsをreturnする必要はない
}
}
class outkeyword01 {
public static void Main() {
double a = 125.3, b = 16.25, c;
MyClass mc = new MyClass();
//cには値を代入していません
mc.Square(a, b, out c); //初期化していないcを参照渡しできる
Console.WriteLine("縦{0}m, 横{1}mの長方形の面積は{2}平方メートル", a, b, c);
}
}
補足:p.194 outkeyword01.csについて
・Squareメソッドは1値を返すようになっているので、outは必須ではない。下記で可能。
public double Square(double x, double y) {
return x * y;
}
アレンジ演習:p.194 outkeyword01.cs
・引数xとyの和と積を返すメソッド public void AddMul(double x, double y, out double add, out double mul) にしよう
作成例
//アレンジ演習:p.194 outkeyword01.cs
using System;
class MyClass{
public void AddMul(double x, double y, out double add, out double mul) { //仮引数add,mulは参照渡し
add = x + y; //よってreturnする必要はない
mul = x * y; //よってreturnする必要はない
}
}
class outkeyword01 {
public static void Main() {
double a = 125.3, b = 16.25, c, d;
MyClass mc = new MyClass();
mc.AddMul(a, b, out c, out d); //初期化していないc、dを参照渡しできる
Console.WriteLine("和は{0}, 積は{1}", c, d);
}
}