本稿は、プログラミング未経験で新人研修でプログラミングをやらされている皆様へ(1)の続きです。
変数とループがあると、ちょっと楽になる
1 + 1なんか、わざわざプログラムを組まなくたって計算できるよ! これが、前の章を読んで皆様が感じたことだと思います。でも、もう少し計算が複雑になったらどうでしょうか?
複利計算をやってみる
会社に入って一番嬉しいことは給料がもらえることでしょう。世の中やっぱり金だよカネ。この金を増やす方法として貯金とか投資とかがあると噂に聞きました。毎月1万円を、月の利回り1%で運用したらどうなるか、プログラムを作って考えてみましょう。
利回りが1%ということは1.01倍すれば良くて、最初は0円スタートなので、最初の月は0 * 1.01 + 1
で表現できそう。翌月はその1.01倍に1を足せばよいので、(0 * 1.01 + 1) * 1.01 + 1
でできそう。これをとりあえず6ヶ月分書いてみたら、こんな感じになりました。
class InvestmentResult {
public static void main(String[] args) {
System.out.println((((((0 * 1.01 + 1) * 1.01 + 1) * 1.01 + 1) * 1.01 + 1) * 1.01 + 1) * 1.01 + 1);
}
}
結果は6.152015060100001で、6万円投資して1,520円しか儲からないので投資に意味はないという間違った印象を持たれちゃいそう。もっと長くやると投資の効果が分かるのですけど、これ以上長く計算式を書いていくのは辛すぎる……。
というわけで、変数を使用してみましょう。
変数を使ってみる
変数は、値の入れ物です。この値の入れ物を使ってちょっと楽になってみる……には、ごめんなさい、準備が必要です。我々人間なら「その結果を」とか「この前のアレを」とかで理解できるのですけど、コンピューターは頭が悪いのでいきなり「それ」と言われても理解できません。だから、まずはこんな名前の変数を使うとJavaに教えてあげなければならないんです。こんな感じ。
double asset = 0; // doubleの値を入れることができる変数assetを宣言し、0を代入する。
double
の部分は、変数に入れる値がどのようなものなのか(これを型と呼びます)を表現しています。コンピューターはその内部で整数と少数、文字と文字列を異なる方式で管理しています。しかも、計算を速くするために、整数や少数では精度はイマイチだけど計算が速いバージョンと、精度は高いけど計算が遅いバージョンを持っていたりします。
で、double
というのは、精度が高い方の少数を表現する型です。少数を扱える型は他にfloat
があるのですけど、これの2倍の精度があるのでdouble
と名前がついているわけ。
asset
の部分は、変数の名前です。自由に名付けていただいて構わないのですけど、使用可能な文字に制限があるので気をつけてください(詳細は新人研修のテキストを見てください)。日本語の名前をつけることも可能なのですけど、英語にしたほうが入力が楽でカッコイイと思います。
=
は、左辺と右辺が等しいことを表しているわけではなくて、代入を意味しています。double asset = 0;
した後は、asset
の値は0になるわけですね。
最後の;
は、文の終わりを意味しています。コンピューターは頭が悪くて「アレしてコレしてソレして」と言われてもどこで区切ればよいのか分からないので、「アレして。コレして。ソレして。」と文を分けて書いてあげなければならないんです。あと、行の終わりはピリオドだろうと考えた方がいるかもしれませんが、ピリオドは小数点を表すのに使ってしまったのでセミコロンになりました。コンピューターは頭が悪いので、この場合は小数点でこの場合は行の終わりと正しく推測させるのは大変なためです(そんなの簡単じゃんと思った方は、「JavaScript セミコロン」で検索してみてください)。
ともあれ、これで変数は宣言できたので、あとは使うだけです。
asset = asset * 1.01 + 1; // 資産に、資産 * 1.01 + 1を代入する。
思い出してください。=
は代入でしたよね? だから、上のプログラムは資産であるasset
に、asset * 1.01 + 1
を代入しています。よって、この行を実行した後は、asset
の値は0 * 1.01 + 1
の結果の1になるわけですね。
あとは、これを繰り返すだけ。1年後の資産残高を表示するプログラムは、以下のようになりました。
class InvestmentResult {
public static void main(String[] args) {
double asset = 0;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
asset = asset * 1.01 + 1;
System.out.println(asset);
}
}
asset
には計算で得た一つの値が入っているので、1 + 1
や"こんにちは"
と同様に、System.out.println()
の括弧の中に書くことができます。
で、結果は12.682503013196973となりました。半年では1,520円でしたが、1年だと6,025円も増えます。金額としてはそんなに大きくはありませんけど、期間が2倍になったら利益が約4倍となったところに投資の凄さを感じます。凄そうなので、ぜひもっと長い期間で計算してみたい!
でも、これを30年分とか繰り返して書くのは辛すぎます。だから、ループを使ってみましょう。
ループを使ってみる
プログラミングでは、繰り返し処理のことをループと呼びます。世の中にはこのループを簡単に記述できるプログラミング言語もあって、たとえばRubyだと以下のように書けばオッケーです。
10.times {
print('繰り返し')
}
これだけで、「繰り返し」という文字列が10回表示されるわけですね。簡単に書けるうえに分かりやすくて素晴らしい!
……でも、我らがJavaにはこんな便利な仕組みはありません。だから、10回「繰り返し」と表示したければ、以下のように記述しなければなりません。
for (int i = 0; i < 10; ++i) {
System.out.println("繰り返し");
}
もしくは、こんな感じ。
int i = 0;
while (i < 10) {
System.out.println("繰り返し");
++i;
}
1つ目の書き方をfor
ループ、2つ目の書き方をwhile
ループと呼びます。まずは、説明が簡単なwhile
ループで説明とさせてください。
while
ループでは、括弧の中の条件が満たされている間、中括弧({}
)の中の処理を繰り返します。今回のプログラムの場合だと、int
型(integerの意味で、整数型です)の変数i
は0で初期化されていますから10未満という条件を満たし、中括弧の中の処理を実行することになって、System.out.println("繰り返し");
で「繰り返し」という文字列を表示します。その次の++i;
はi
に1を足すという意味になります。i = i + 1;
と書かないのは、1を足したり1を引いたりするのはプログラムの中で頻繁に実行されるので、CPUに1足したり1引いたりする専用の回路が用意されていて、それを使った方が実行が速いためです。あと、短いので書くのが楽ですしね。
0が代入されていたi
に++i
することで、i
の値は1になります。ここまでで中括弧の範囲は終わりですから、コンピューターはwhile
に戻って、括弧の中の条件を満たすか確認します。1は10未満ですからやっぱり条件を満たすので、中括弧の中が実行されます。中括弧の中を実行すると++i
されてまたi
の値が1増えて……を繰り返していくとやがてi
の値は10になって、while
の括弧のi < 10
が満たされなくなって、これでwhile
ループは終了。コンピューターはwhile
ループの次に書いてある文を実行します。
for
ループは、これの短縮形です。for
の後の括弧の中に、セミコロンで区切って変数の宣言と初期化; ループを繰り返す条件; 変数の値を変更する操作
を書きます。while
よりも書くのが簡単なので、10回繰り返すような単純なループは、一般にfor
ループで書きます。
あと、蛇足なのですけど、なんでループの変数名にi
を使うのかというと、最初に作られたプログラミング言語のFORTRANがループなどで使う整数型の変数はI〜Nと決めちゃったから。なんでFORTLANがそんな取り決めをしたのかというと、数式で繰り返しを表現するΣでiが使われることが多かったから。数学でiを使うことが多かったのは、多分、indexのiなんじゃないかな。
さて、説明が長くなってしまいましたが、ループの説明を始めたのは、投資の効果をループを使用して確認するためでした。なので、毎月1万円を、月の利回り1%で30年間運用した場合にどうなるかをプログラミングしてみます。こんな感じ。
class InvestmentResult {
public static void main(String[] args) {
double asset = 0;
for (int i = 0; i < 30; ++i) { // 30年分のループ
for (int j = 0; j < 12; ++j) { // 12ヶ月分のループ
asset = asset * 1.01 + 1;
}
}
System.out.println(asset);
}
}
外側の変数i
を使っているfor
ループで30年分の繰り返しを、内側の変数j
を使っているfor
ループで12ヶ月分の繰り返しをやっているわけですね。
で、その結果は、なんと3494.9641327684994になりました。30×12は360万円なので、実に3,134万9,641円の利益です。投資ってすごいですな!……普通利回りは年で表現するもので、月1%の利回り(今プログラムを組んで計算してみたら、年利回り12.7%に相当します)なんて非現実的だからこの結果に意味はないだろという反論は、ごめんなさい、却下で。私は貯金も投資をやったことがないので、この分野に疎いんです。
ともあれ、変数もループも便利なのは本当です。電卓では面倒すぎてやれないような計算を、変数やループを駆使していろいろ試してみてください。お疲れさまでした。