「足し算」の定義

ホームC#入門講座第1章:世界へのトビラ > 「足し算」の定義

「足し算」の定義

3種類の足し算

突然ですが、問題です。素直にお答えください。そうすれば当たります。

(問1) 123 + 123 を計算せよ
(問2) "123" + "123" を計算せよ
(問3) "123" + 123 を計算せよ

答えはプログラムに聞いてみます。

using System;

namespace NewWorld
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			Console.WriteLine(123 + 123);
			Console.WriteLine("123" + "123");
			Console.WriteLine("123" + 123);
			
		}
	}
}

実行結果は以下のようになりました。

246
123123
123123

この結果から、少し考えを膨らませてみましょう。

厳密な足し算

私たちが足し算という言葉を使うとき、どのような意味で使っているのでしょうか。厳密に定義してみてください。

要するに「+」の左辺と右辺を合計するという意味で使っているのではないでしょうか。すなわち、上記の例だと 123 という数と 123 という数の「和」ということになります。

しかし、2つ目の問題では"123"という文字列と"123"という文字列を「足し算」しています。この場合の「足し算」はどういう意味で使っているのでしょうか。

要するに、「つなげる」という行為を「足し算」として定義しています。「連結」こそが文字列の「足し算」の意味であり、そこには「和」とか「算」という操作は入ってきません。

このように、プログラムでは「+」に複数の意味を持たせています。一つは「加算演算子」として、もう一つは「文字列連結演算子」としての意味で定義しているのです。このように、同じ「足し算」でも実際の操作・処理は別です。人間がなんとなく似ていると思うから、そのように複数の定義を持たせただけです。

実際に「+」記号には、自分で定義を加えることができます。代表的な例だと、「座標を加算する」という定義を付け加えるものがあります。ただ、それは高度過ぎるのでここでは扱いません。大事なのは厳密な定義を考えることです。

あいまいな人間

では、最後の "123" + 123 はどのような結果を意図して記述したのでしょうか。「+」を文字列連結演算子として解釈してほしかったのか、加算演算子として解釈してほしかったのか、私たちは判断することができません。プログラムの仕様によって、これは自動的に文字列連結演算子と判断されているようです。

問題は、両辺で型が違うことです。左辺は string なのに、右辺は int です。一体どうやって string と int を「足し算」するのでしょうか。その定義は非常にあいまいであり、これはよくないプログラムの例です。場合によっては想定外の結果を吐き出してしまいます。

この問題を解決するには、「型変換」を行います。例えば、int を string に変える場合はこのようにします。

Console.WriteLine("123" + 123.ToString());

123は int 型なので、int型に備わった「ToString()メソッド」を呼び出しています。数字から直接メソッドが出てくるのに違和感があるなら、このように解釈してください。

int i = 123;
Console.WriteLine("123" + i.ToString());

一方、string を int に変える場合は別の方法を使います。

Console.WriteLine(int.Parse("123") + 123);

int型に備わった「Parse()メソッド」はstringをintに変換する機能を持っています。こうすることによって、結果は246になり、123123ではなくなります。

型変換にはほかにキャストと呼ばれる方法があります。それはまた出てきたときに解説することにします。よりよいプログラムを組むようにすれば、あまり出てくることはありません。

具体的な例

型変換が必要になるのは、ユーザーから数字の入力を受けた場合が多いです。例えば、ユーザーから文字列の入力を求める「ConsoleクラスのReadLine()メソッド」を使用して次のようなサンプルプログラムを作成しました。

using System;

namespace NewWorld
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			Console.WriteLine("A + B を計算します");
			Console.WriteLine("整数Aを入力してください");
			string a = Console.ReadLine();
			Console.WriteLine("整数Bを入力してください");
			string b = Console.ReadLine();
			
			Console.WriteLine("A + B = {0}",a + b);
		}
	}
}

このプログラムを実行すると予期せぬ結果になります。たとえば、12と21を入力した場合、33ではなく1221になります。これが「加算演算子」のつもりで使用したのに、「文字列連結演算子」として実行された例です。

ここではReadLine()メソッドが string で文字列を取得していることに注意せねばなりません。よって、プログラムのどこかでstringをintに変換する処理が必要です。

Console.WriteLine("A + B を計算します");
Console.WriteLine("整数Aを入力してください");
int a = int.Parse(Console.ReadLine());
Console.WriteLine("整数Bを入力してください");
int b = int.Parse(Console.ReadLine());

Console.WriteLine("A + B = {0}",a + b);

このようにして入力された直後、変数に代入する直前でintに変換しておきます。このようにすれば、期待どおりの結果を得ることができます。

ユーザーから数値を入力してもらう場合は常に注意するようにしてください。