連載
プロフェッショナルVB.NETプログラミング
第2回 データ型の処理
(株)ピーデー
川俣 晶
2002/04/04
|
|
整数型の表現力
「何でも入る魔法の箱」は便利ではあるが、いざトラブルが起こったときに原因が分かりにくいという問題がある。また、処理効率が落ちて、実行速度が低下するという危険もある。個々の変数のデータ型を明確に指定すれば、性能と信頼性の両方を向上させることができる。では、整数などの個々のデータ型は、VB 6からVB.NETに変わるときに、何か機能の変更が行われているだろうか。実は整数型は大きく変化しているのである。以下のサンプル・ソースを見比べていただきたい。まずは、VB 6で記述した整数型を使用するサンプル・ソースから。
1: Private Sub Form_Load()
2: Dim i1 As Integer, i2 As Integer
3: Dim l1 As Long, l2 As Long
4: i1 = -32768
5: i2 = 32767
6: l1 = -2147483648#
7: l2 = 2147483647
8: Debug.Print i1, i2, l1, l2
9: End Sub
|
|
整数型を使用したVB 6のサンプル・プログラム5 |
このサンプル・ソースでは、整数型の各データ型の最小値と最大値を代入して、確かにそれが格納可能であることを確認している。これを実行すると、以下のような結果になる。
-32768 32767 -2147483648 2147483647 |
|
サンプル・プログラム5の実行結果 |
なお、6行目の最後に#が付いているのは、2147483648が整数としては表現できないという理由により(正の整数の最大値は2147483647)、倍精度浮動小数点値として扱うように指示しているものだ。実行結果を見れば明らかなように、内部的にはLong型整数で-2147483648を扱うことは可能だが、ソース・コードを評価する際には「-」と「2147483648」の組み合わせとして処理されるため、エラーが起こってしまうという事情による。
さて、これと同じ趣旨のものをVB.NETで記述すると以下のようになる。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim s1 As Short, s2 As Short
3: Dim i1 As Integer, i2 As Integer
4: Dim l1 As Long, l2 As Long
5: s1 = -32768
6: s2 = 32767
7: i1 = -2147483648
8: i2 = 2147483647
9: l1 = -9223372036854775807 - 1
10: l2 = 9223372036854775807
11: Trace.WriteLine(s1 & ", " & s2 & ", " & i1 & ", " & i2 & ", " & l1 & ", " & l2)
12: End Sub
|
|
サンプル・プログラム5をVB.NETで書き換えたサンプル・プログラム6 |
9行目がまわりくどい記述になっているが、これも上のソースの6行目に#が付いているのと同じ理由である。この値は大きすぎて倍精度浮動小数点でも表現できず、2つの整数を演算することで作り出している。
さて、これを実行すると以下のような結果になる。
-32768, 32767, -2147483648, 2147483647, -9223372036854775808, 9223372036854775807 |
|
サンプル・プログラム6の実行結果 |
見て分かる通り、2つの点で、大きな相違が生じている。第1の相違は、同じ名前でも表現できる数値の桁数が大幅に増えていることだ。VB 6のInteger型はたかだか32767までしか扱うことができず、安月給の金額すらオーバーフローしてしまうのだが、VB.NETのInteger型は2147483647まで表現することができ、相当の高給取りの給料でもオーバーフローしない表現力が与えられている。第2の相違は、Short型の創設である。Interger型の桁数が増えたことに対応して、旧Integer型に対応する範囲の値を格納するShort型が生まれた。
一見、そんなまわりくどいことをしなくても、IntegerとLongはそのままで、Longよりも大きな桁数を持つ“LongLong”を追加すればよいと思うかもしれない。だが、取りあえず整数をIntegerで表現する習慣のあるプログラマーも多いだろうことを考えれば、最も処理効率のよい整数型をIntegerに割り当てることも悪くない選択といえる。32bit CPUなら、32bitで表現される整数が最も効率よく扱えるので、Integerを-2147483648〜2147483647の範囲の整数(つまり32bit符号付きの表現範囲)に変更するのは意味あることだ。
もちろん、そのような変更で桁数が減ってしまうことがあれば、互換性上の問題が生じるが、桁数が増える分には、トラブルの種にもなりにくいだろう。もちろん、整数型の表現するビット数に依存するプログラミングを行っている場合は要注意である。
デフォルトのデータ型
VB 6には、“Def”の3文字で始まるステートメントがあり、変数のデフォルトのデータ型を指定することができる。例えばDefIntは、変数のデフォルトのデータ型が整数型(Integer)であることを示す。“DefInt A”と記述したソース上で、文字「A」で始まる変数名を使用すると、それはIntegerであると見なされる。かつて筆者が使っていた1979年発売のパソコン、PC-8001に搭載されていたMicrosoft製のN-BASICにもあったものだから、非常に古く伝統ある由緒正しい機能といえる。以下は、それを実際に記述したサンプル・ソースである。
1: DefInt A
2: DefSng B
3:
4: Private Sub Form_Load()
5: a = 1.2
6: b = 1.2
7: Debug.Print a, b
8: End Sub
|
|
“Def〜”のステートメントを使用したVB 6のサンプル・プログラム7 |
これを実行すると以下のような結果が得られる。
5行目で初めて出現する変数aは、1行目のDefInt Aの効能により、Integer型と見なされる。そのため、1.2を代入しても整数に丸められ、1という値が格納される。一方、6行目の変数bは、2行目のDefSngの効能によりSingle型と見なされ、小数点以下の値も保存される。
これに相当するソースはVB.NETでは記述できない。というのは、Defで始まるDefIntなどのステートメントは一切存在しないためである。強いて書けば以下のようになる。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Integer, b As Single
3: a = 1.2
4: b = 1.2
5: Trace.WriteLine(a & ", " & b)
6: End Sub
|
|
データ型を明示してサンプル・プログラム7に似せたVB.NETのサンプル・プログラム8 |
これを実行すると以下のようになる。
見ての通り、変数ごとにデータ型を明示するように記述するよりほかに方法はない。しかし、この世の中で、先頭の1文字が共通なら同じデータ型などという都合のよいソースがそうそうあるわけがなく、Defで始まるステートメントは現実には使えない機能だったと考えた方がよいだろう。これはあくまで、可読性を落としてもソースを短くしなければならなかった初期のパソコンでのみ利用価値のあった機能といえる。事実、昔の8bitパソコンでは、処理速度の向上と省メモリのためにプログラム先頭で“DEFINT A-Z”などと記述することも多かった。だが、それはすでに過去の話である。
Insider.NET 記事ランキング
本日
月間