この Notebook は,
テキスト「オープンソースソフトウェアによる情報リテラシー −第2版−」の
のプログラミング部分に相当する内容を xeus-cling という Juypter kernel を利用して書いてみたものです。
xeus-cling
is a Jupyter kernel for C++ based on the C++ interpreter cling and the native implementation of the Jupyter protocol xeus.
Cling は C++ のインタープリターです。 章番号はオリジナルの従来テキストに対応するように8章からはじめています。
通常の C++ のソースでは,以下のように main()
でブログラム文を {}
で囲みますが...
#include <iostream>
using namespace std;
int main()
{
for(int i = 1; i <= 5; i++) {
cout << "こんにちは, C++ の世界! " << i << endl;
}
return 0;
}
Cling は,C++ のインタープリタ実装であり,以下のように main(){ }
なしで実行できます。
#include <iostream>
using namespace std;
for(int i = 1; i <= 5; i++) {
cout << "こんにちは, C++ の世界! " << i << endl;
}
Cling は C プログラムも理解するようですが,最後に 13
と表示します。
#include <stdio.h>
printf("Hello World!\n")
Cling に標準でついてくる Jupyter kernel もありますが,本稿執筆時点で,cin でエラーがでないのは,こちらの xeus-cling でした。
int a;
cin >> a;
cout << "今入力した整数は " << a << " ですね\n";
エンゲル係数とは,家計の消費支出に占める飲食費(食料費,食費)の割合(パーセント単位)です。
消費支出 110,000円,飲食費 37,000円の人のエンゲル係数を求めるプログラム例。
本稿のように Jupyter Notebook 環境では,セル内で Enter キー(Return キー)を押すと改行され,最後の行を書いたあとに,Shift キーを押しながら Enter キー(または Return キー)を押して実行します。
cout << 37000 * 100. / 110000;
割り算を先にしたり,100.
の小数点をつけずに 100
として計算すると,不思議な答えが表示されますが,それについては後ほど解説します。
cout << 37000 / 110000 * 100.;
cout << 37000 * 100 / 110000;
ここからは,単に電卓的に使うだけではなく,応用・発展も見据えて以下のようなプログラム文を作成して実行することにします。
以下の例では,
s1
に消費支出である 110000
(円)という数値を代入し,s2
に飲食費である 37000
(円)という数値を代入し,x1
に代入し,x1
を表示させています。変数 s1
, s2
は int
(整数), x1
は double
(浮動小数点型の実数)としています。小数点以下の部分を持つ実数を表す浮動小数点型は,float
, double
, long double
の3種類がありますが,この Notebook では詳細は省き,double
で統一して説明します。
int s1 = 110000;
int s2 = 37000;
double x1 = s2 * 100. / s1;
cout << x1;
意に反して,プログラムがうまく動作しない場合があります。たとえば,上記の 3行目を以下のように書いた場合。
掛け算を示す演算子は *
,割り算を示す演算子は /
であるところを誤って,×
や ÷
と書くと,これらの記号は Python では演算子として定義されていないのでエラーとなります。Jupyter Notebook では,以下のように誤りやその箇所を指摘してくれます。
int s1 = 110000;
int s2 = 37000;
double x1 = s2 × 100. ÷ s1;
cout << x1;
別の種類の誤りもあります。たとえば,3行目の「100.」(パーセントで表すときは 100 をかけるのでした)を「1000.」と入力した場合...
int s1 = 110000;
int s2 = 37000;
double x1 = s2 * 1000. / s1;
cout << x1;
上記の例では Error
の警告が出ませんが,答えは明らかに変です。(エンゲル係数の最大値は100だから。)
このような場合はコンピュータにとって誤りではなく,指示通りに計算し,その結果を表示します。 このようなプログラム作成者の不注意や勘違いによって生じるエラーには注意が必要です。
プログラムが正しく動作しない場合は,誤りの箇所を探し,修正して再度動作を確認します。正しく動作するようになるまで,プログラムを修正し,実行(Jupyter Notebook 環境では Shift + Enter)します。この作業をデバグといいます。
上記の例の 1行目では,s1
という名前の変数に 100000
という数値を代入しています。変数名はアルファベットで始まる英数字列にします。大文字と小文字は区別されます。
小数点以下を含まない場合には整数型 int
です。
3行目の最後,"\n"
は改行を表します。4行目のように,endl
としてもよいようです。(厳密には "\n"
と endl
は違うようですが。)
int s1 = 100000;
int S1 = 40000;
cout << S1 << "\n";
cout << s1 << endl;
変数 ss
に文字列を代入する場合は,以下のようにします。文字列を扱う型は,string
です。利用時には最初に #include <string>
としてやる必要があります。
#include <string>
string ss = "エンゲル係数";
cout << ss;
string x0 = "エンゲル";
string y0 = "係数";
cout << x0 + y0;
文字列と数値を直接連結することはできません。
int s1 = 110000;
int s2 = 37000;
double x1 = s2*100./s1;
cout << "エンゲル係数は " + x1;
そんなときは,数値を文字列に変換する関数 to_string()
を使います。
int s1 = 110000;
int s2 = 37000;
double x1 = s2*100./s1;
cout << "エンゲル係数は " + to_string(x1);
cout
のところは,わざわざ文字列に変換して連結しなくても,以下のようにも書くことができます。
cout
文は,<<
によって複数の項目(変数)を連結して表示することができます。
int s1 = 110000;
int s2 = 37000;
double x1 = s2*100./s1;
cout << "エンゲル係数は " << x1 << " です。";
cout << 2 + (50 - 5 * 6)/4;
除算 /
の例を以下に示します。
1行目では,整数を整数で割るので,小数分を切り捨てた整数値を返します。
2行目では,17.
と最後に小数点をつけたので,double
型の値を返します。
cout << 17 / 3 << endl;
cout << 17./ 3 << endl;
これで,最初のほうで述べた以下の表示の謎が解けましたね。
cout << 37000 * 100. / 110000;
cout << 37000 / 110000 * 100.;
cout << 37000 * 100 / 110000;
べき乗(累乗)を表す演算子は C++ ではありません。$2^4$ の計算をするには,最初に
#include <cmath>
して pow()
関数を使います。引数には double
型の数値を入れます。
#include <cmath>
// macOS では,以下はエラーとなります。Ubuntu では無問題。
// cout << pow(2, 4);
// 以下は,macOS でも Ubuntu でも無問題。
cout << pow(2., 4.);
上記の例では,プログラムの中で消費支出や飲食費を決めていましたが,今度はプログラムを実行する人が入力できるようにしてみます。
以下のプログラム例では,cin >> s1
でキーボードからの入力値を変数 s1
に入れます。
int s1, s2;
cout << "消費支出? ";
cin >> s1;
cout << "飲食費? ";
cin >> s2;
cout << "エンゲル係数は " << s2 * 100. / s1;
(これまでの例では1回しか計算していませんが)よく使う計算を「関数」として定義する例です。
以下の例では,エンゲル係数を計算する関数 calc()
を定義しています。
//
で始まる行はコメント行です。コメント行はそれを読む人間のための注釈であり,プログラムの実行時には無視されます。
double calc(int s1, int s2) {
// ここはコメント行。s1 は消費支出,s2 は飲食費,エンゲル係数を返す。
return s2 * 100. / s1;
}
以下では,3行目で calc()
を呼び出しています。
int s1 = 110000;
int s2 = 37000;
double x1 = calc(s1, s2);
cout << "エンゲル係数は " << x1;
いったん定義された関数は,以下のように何度でも使用できます。
cout << calc(120000, 43000);
消費支出を入力すると,エンゲル係数が 20 ~ 40 となる飲食費を表示するプログラムをつくりなさい。
関数は上記の例のように自分で定義することもできますが,あらかじめ用意されている「組み込み関数」を使うこともできます。
以下では,組み込み関数の例として,
floor()
round()
を使用しています。
ceil()
です。int s1 = 130000;
int s2 = 53000;
double x1 = calc(s1, s2);
cout << "エンゲル係数は " << x1;
cout << ": floor(x1) = " << floor(x1);
cout << ": round(x1) = " << round(x1) << endl;
小数点以下を切り上げたエンゲル係数の値を表示させるように上記のプログラムを変更しなさい。
条件分岐とは,例えばエンゲル係数の値によって実行文を変えることです。例を示します。
以下では,何回かこのプログラムを実行させるので,呼び出しやすいように関数 engel()
として定義してしまいます。値を返さない関数なので void
型の関数として定義します。
void engel()
{
int s1, s2;
cout << "消費支出? ";
cin >> s1;
cout << "飲食費? ";
cin >> s2;
double x1 = calc(s1, s2);
if (x1 >= 80)
cout << "エンゲル係数は " << x1 << " です。飲食費を使いすぎです。";
else
cout << "エンゲル係数は " << x1 << " です。";
}
定義した関数 engel()
の使い方は以下のようにします。
engel()
engel()
条件分岐の if
文の書式は以下のようになっています。
if (条件式1)
条件式1 が満たされた場合に実行する文;
else if (条件式2)
条件式2 が満たされた場合に実行する文;
else
それ以外の場合に実行する文;
上記の条件分岐を,エンゲル係数が
と表示させるように変更しなさい。
以下の例では,1行目で代入された消費支出に対してエンゲル係数を計算します。
1回だけ計算して表示するのではなく,2行目の飲食費の初期値(ここでは 40000
円)から,5行目の条件式(ここでは 80000
円以下)が成り立つ場合に,8行目にあるように 5000
円ずつ増やしながらエンゲル係数を表示します。
8行目の +=
は復号代入演算子と呼ばれるものの一つです。この場合の =
は「等号」ではなく「代入」の意味で,右辺の値を新たに左辺の変数に代入する,という意味です。
s2 += 5000;
は以下と同等。
s2 = s2 + 5000;
また,プログラム文でよく見かける
i++
は,
i += 1
や
i = i + 1
と同じ意味です。
while
文による繰り返し¶int s1 = 110000;
int s2 = 40000;
cout << "消費支出 " << s1 << " 円に対するエンゲル係数の値" << endl;
while (s2 <= 80000) {
x1 = calc(s1, s2);
cout << " 飲食費 " << s2 << " 円の場合: " << x1 << endl;
s2 += 5000;
}
while
文の書式は以下のとおりです。
while (条件式) {
条件式が成り立つ場合に実行される文
}
for
文による繰り返し¶int s1 = 110000;
cout << "消費支出 " << s1 << " 円に対するエンゲル係数の値" << endl;
for (int s2 = 40000; s2 <= 80000; s2 += 5000) {
x1 = calc(s1, s2);
cout << " 飲食費 " << s2 << " 円の場合: " << x1 << endl;
}
for
文の書式は以下のとおりです。
for (int ivar = istart; 条件式; ivar の増減式) {
整数変数 ivar が istart から条件式が成り立つ間,実行される文;
実行後は ivar の増減式により ivar の値が変化し,
条件式が成り立つ間,繰り返される。
}
以下の値を求めるプログラムを作成せよ。
$$\sum_{n = 1}^{10} n^2$$