元ネタ:http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26141&forum=7&67
意外と知られていないのかな?
種類 |
型 |
最小値 |
最大値 |
サイズ(符号有無) |
整数型 |
sbyte |
-128 |
127 |
8 bits(有) |
byte |
0 |
255 |
8 bits(無) |
short |
-32,768 |
32,767 |
16 bits(有) |
ushort |
0 |
65,535 |
16 bits(無) |
int |
-2,147,483,648 |
2,147,483,647 |
32 bits(有) |
uint |
0 |
4,294,967,295 |
32 bits(無) |
long |
-9,223,372,036,854,775,808 |
9,223,372,036,854,775,807 |
64 bits(有) |
ulong |
0 |
18,446,744,073,709,551,615 |
64 bits(無) |
char |
0 |
65,535 |
16 bits Unicode 文字セット |
|
|
おおよその範囲 |
(有効桁数) |
浮動小数点型 |
float |
±1.5 × 10-45 ~ ±3.4 × 1038 ; |
32 bits(7 桁) |
double |
±5.0 × 10-324 ~ ±1.7 × 10308 |
64 bits(15 桁) |
decimal 型 |
decimal |
±1.0 × 10-28 ~ ±7.9 × 1028 |
128 bits(28 桁) |
コンピュータの中では、数字は 2 進数で記録されます。 2 進数とは、 2 つの数字を使って、数字を表します。つまり、スイッチのオン/オフ、電圧が低い/高いという 2 つの状態を、数字として使っています。
普段我々は、10 進数を使います。10 進数は、0 ~ 9 の、10 個の数字を使います。0 ~ 9 まで使ってしまうと、桁上がりをします。 2 進数では、0 ~ 1 まで進むと桁上がりをします。
1つのスイッチで 2 つの数字を表せます。つまり、0 と 1 です。 2 つのスイッチがあれば、2 * 2 で 4 つ、3 つあれば 2 * 2 * 2 で 8 個の数字が表せます。数字には 0 があるので、表すことが出来る数字の数から 1 つ引いた値が、最大の数字ということになります。数式で表すと、2n - 1 となります。
しかし、これでは大量に「桁」が必要になります。10 までカウントしようとしても、5 桁4 桁(4 桁あれば 24 = 16 個の数字が表せます)も必要になります。その為、4 桁3 桁または 8 桁4 桁をまとめて 8 進数、16 進数として表現することが多いです。
正の整数はこれで良いとして、次に負の整数です。我々は "-" マイナスを使って負の数を表します。しかし、コンピュータ…というより、「有る/無し」しかない世界で、「マイナス」の概念はありません。その為、最上位のスイッチを「符号」と規定し、マイナスを表現するようになりました。このため、符号有りでは、符号なしに比べて最大の数字が約半分になってしまいます。また、4 桁の符号有り 2 進数として「1000」は、何を示すでしょうか。「-0」?「無い」ものに正も負もありませんから、「-0」は有りません。なので、数字が割り当てられます。このため、負の数の方が 1 つ多く数字を表すことが出来ます。
次に実数です。実数を表現する方法としていくつかありますが、C# では浮動小数点型の float と double があります。浮動小数点型とは、小数点の位置が決まっていないことを表しています。"0.12e2" という表現を見かけたことはないでしょうか。これは "0.12 × 102" で、"12" を表します。この場合、× 102 と修飾することで、12 の後ろにある小数点を 12 の前に動かしています。この 12 に 90 を足して 102 になったときには、0.102e3 として、また小数点の位置を動かします。このように、表示されている小数点の位置と、本当の小数点の位置が違います。このような表記をする型を、浮動小数点型と言います。
.NET Framework では、float と double は IEEE 754 フォーマットを使って表されています。これは、対象の数字を 2 進数表記にして、最左端のビットが 1 になり、その次に小数点がくるように、桁を動かします。最左端は 1 と決まっているので、仮数部では省略します。数式で表すと、
「(-1)符号部 * 仮数部 * 2指数部」
となります。ここで、符号部は 正の時 0、負の時 1。仮数部は 2 進数。指数部は仮数を元に戻すために移動させる小数点の桁数になります。
例:11.2
11.2(D) = 1011.00110011…(B)
符号部は 0
仮数部は 01100110011…(B)
指数部は 3(D)
ここで、0.2 を 2 進数で表現できないため、仮数部が、単精度の場合 24 桁、倍精度の場合 53 桁で打ち切られます。打ち切りの方法は、選択できます。打ち切られる以上、極わずかですが、誤差が発生します。誤差が発生することがわかっているので、それぞれの精度よりも少ない精度で実質的な精度を決め、誤差の修正をします。
このように、double および float 型は、与えられた小数部を含む数字をそのまま 2 進数として内部に保持するため、21/n 2-n の和で表せない小数を、正しく保持することが出来ません。
ところが、decimal では、この誤差が発生しません。28 桁まで、10 進数の数字をそのまま保持することが保証されています。なぜなのかが書かれた資料を見つけられていないのですが、decimal 型の表記が
『(-1)符号部 * 仮数部 * 10-指数部』
であることから、仮数部に整数を使っているため、と考えられます。
例:11.2
11.2(D) = 112 * 10-1
符号部は 0
仮数部は 112(D)
指数部は 1
では、なぜ double と decimal があるのでしょうか。コンピュータの利用可能な資源が貧弱だった過去からのしがらみとか、説明し出すと退屈なので割愛します。一言。
それぞれの型の特徴をよく理解して、適材適所で用いること
11/23 : 桁数の計算を間違えていました。
投稿日時 : 2005年11月22日 22:42