右見て左見て

ホームC#入門講座第1章:世界へのトビラ > 右見て左見て

右見て左見て

数学における等号演算子

さて、突然ですが質問です。

(例題)

x = 10 とする。
はたして
x = x + 1
は成立するか。

これは数学の概念を用いて解くか、プログラミングの概念を用いて解くかによって答えが変わってきます。

(数学の概念を用いた解)

x = x + 1 の左辺は x = 10 より
(左辺) = x = 10
一方、右辺は
(右辺) = x + 1 = 10 + 1 = 11
よって、左辺と右辺が異なるので成立しない。

(別解)

x = 10 はこの問題では関係ない。
x = x + 1 を移項して、
x - x = 1 となり、整理すると
0 = 1 となって明らかに不適。
よって成立しない。

以上が数学の概念です。数学では「=」に「左辺と右辺の値が等しい」という意味を与えています。だから左辺と右辺を比較することもできるし、移項することもできるのです。このような「=」は「等号演算子」と呼ばれます。

プログラミングにおける代入演算子

一方、プログラミングの概念を用いて先ほどの問題を解くと、このようになります。

(プログラミングの概念を用いた解)

x = 10 より、右辺を左辺に代入して x は10である。
x + 1 は、x が10であるので、11である。
x = x + 1 より、x + 1 は11であるから右辺は11に等しく、
よって右辺を左辺に代入して左辺も11。

ゆえに、問題は成立し、最終的な x は 11 を保持する。

ここで注目してほしいのが、「右辺を左辺に代入」という言葉です。実は、プログラミングにおいて「=」に付加された意味は「右辺を左辺に代入する」という意味なのです。

using System;

namespace NewWorld
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			int x = 10;
			x = x + 1;
			Console.WriteLine(x);
		}
	}
}

このプログラムの実行結果は11です。x = x + 1; の行でもエラーにはなりません。

重要なのは右を見て、左を見ることです。10を見てxを見るからxは10。x + 1を見て11を思い浮かべてxを見るからxは11。必ず右から左へいきます。これを「代入演算子」と呼びます。

ではプログラミングにおける「等号演算子」とは何か。じつは、「==」と、イコールを2つつなげて初めて「等号演算子」になるのです。プログラミングではこの2つを厳密に区別しますから、きちんと理解してください。

変数の型

上で紹介したのが、いわゆる「変数」です。変数自体は数学でも扱うので、なんの問題もないでしょう。問題になるのはむしろ「型」です。型とは、上のサンプルで x という変数名の直前に記述している int がその一種です。

10と10兆は、はたして同じ「数」の仲間でしょうか。あるいは、やせっぽっちの人とお相撲さんが占める席の面積は同じでしょうか。場合によれば、お相撲さんは2人分の座席料金を請求されかねません。

同様に、10と10兆では、メモリの領域を消費する量が違います。そのような違いに対応するため、「型」があります。

普通の整数であれば、たいてい4バイト分で十分です。ですが、20億くらいから危なくなってきます。その場合は倍の8バイト用意します。小数の場合も8バイト用意します。1バイトは8ビットですから、それぞれ32ビットと64ビットということになります。

変数の型メモリの量
int32bit整数
float32bit小数
long64bit整数
double64bit小数
decimal128bit金融計算用
char16bit文字
string文字列

このうちよく使うのが int/double/char/string です。stringだけは特殊な型で、ある一定のメモリを消費するわけではありません。詳しくは後ほど。

注意してほしいのは char は16bitだということです。欧米の文字は1文字1バイト(8bit)で表せますが、日本語や中国語はマルチバイト文字と呼ばれ、2バイト(16bit)必要になります。これは英語圏からすれば「8bitで十分なところを16bitも消費する」という意味で無駄ですが、世界共通語としての意識からC#ではUnicodeを採用しているためです。

また、'c' のようにシングルクォーテーションで囲むと char になり、"c" のようにダブルクォーテーションで囲むと string になります。同様に、10 と書くと int ですが、10.0 と書くと double になります。変数の型は極めて厳密なので注意してください。

2の32乗は?

intは32bit、つまり2の32乗だけ数値を保持できるわけですが、いったい2の32乗はいくらでしょう。プログラムを使って求めてみました。

using System;

namespace NewWorld
{
	class MainClass
	{
		public static void Main(string[] args)
		{

			Console.WriteLine(Math.Pow(2,32));
		}
	}
}

結果は4,294,967,296でした。だいたい43億です。ですが、コンピュータでは最初のビットは正負を表すために使われるので、実際は2の31乗、これの半分です。だからマイナス20億くらいからプラス20億くらいまでは int でカバーできます。

上のソースコードに登場する Math.Pow() は「MathクラスのPow()メソッド」です。Console.WriteLine()と同じですね。見てのとおり、Pow(x, y)として、xのy乗を求めます。Mathクラスにはこのような様々な数学関連のメソッドが用意されています。

C#における型の神秘

C#における「型」は上に挙げたものだけではありません。「型」とはこれまでに少しだけ触れてきた「クラス」にほかならず、自分でいくらでも型が作れます。また、C#ではあらかじめたくさんのクラスが用意されているので、それらのクラスを使いこなす際は型に注意する必要があります。

今回は例として、「DateTime構造体」を取り上げてみます。「構造体」とは「クラス」によく似たものです。ここでは気にしないでください。

using System;

namespace NewWorld
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			DateTime moment = DateTime.Now;
			int year = moment.Year;
			int month = moment.Month;
			int day = moment.Day;
			int hour = moment.Hour;
			int minute = moment.Minute;
			int second = moment.Second;
			
			Console.WriteLine("現在は{0}年{1}月{2}日 {3}時{4}分{5}秒です", year,month,day,hour,minute,second);
			
		}
	}
}

このプログラムは初級としては高度で、すべてを理解する必要はありません。一番最初のこの部分を見てください。

System.DateTime moment = System.DateTime.Now;

これは「DateTime型」の変数として moment を定義し、System.DateTime.Now というものを代入しています。(Nowの働きなどは後日。)

このように、数字以外の様々な「型」がクラス(ここでは構造体)から出てきますから、それらをうまく活用する必要があります。

なお、ここでのWriteLine()メソッドの方法は特殊です。見たら直感的に分かると思いますから、うまく活用してください。