Pythonでの整数型の定義と最大値
Pythonの数値の表現として最もよく使われるものは整数型(int型)です。整数型は、コンピュータの性能が許せばどんなに大きな数字も扱うことができます。
Pythonで整数の計算をする
Pythonにおいて、変数に整数の値を小数点なしで代入すると整数型として定義されます。整数に関する四則演算をするときには、割り算を除き整数型で結果が返ります。
整数型の定義と計算
整数型の演算と型
- x = 2
- y = 5
- za = x+y
- zs = x-y
- zm = x*y
- zp = x**y
- print(za, zs, zm, zp)
- print(type(x), type(za), type(zs), type(zm), type(zp))
7 -3 10 32 <class 'int'><class 'int'> <class 'int'> <class 'int'> <class 'int'>
3.~6. 整数型として定義した変数x,yに対し和、差、積、べき乗を計算し、変数に代入します。
7. 整数として結果が表示されます。
8. 結果につきtype関数を使い変数の型を確認するとint型(整数型)になります。ちなみにintはinteger(整数)の略です。
文字型との関連
クォート('...')を付けて数字を定義すると文字型(str型)
として定義されます。文字型を使うと数学的な演算をすることができないので、int関数により整数型に変換する必要があります。
整数型との関連
- xi=12
- xs='34'
- print(type(xs))
- print(xi+int(xs))
- print(str(xi)+xs)
- print(xi+xs)
<class 'str'> 46 1234 TypeError: unsupported operand type(s) for +: 'int' and 'str'
3. クォート('...')を付けて変数xsを定義すると、変数はstr型(文字列型)になります。ちなみにstrはstring(文字列)の略です。
4. 文字列型で定義した変数xsを使い足し算などの計算をするときは、int関数を使い整数型に変換してから演算します。
5. 整数型として定義した変数xiを文字列として操作するときは、str関数を使い文字列型に変換してから演算します。複数の文字列型の変数に+演算子を適用すると、文字列が結合されます。
6. 整数型の変数と文字列型の変数に+演算子を適用するとエラーになります。
Pythonではどんなに大きな整数でも扱うことができる
IPアドレスの最大値も計算できる
紙と鉛筆でやれば一生かかるよう計算もPythonはたちどころにやってのけます。身近なところでは、インターネットにつながるコンピュータや携帯電話などの機器を識別するためのIPアドレスがあります。IPアドレスはこれまでIPv4というルールで、32ビットの数字を使い世界中でインターネットにつながる機器を管理していました。ところが、これでは管理できる数が限界となったので、128ビットの数字を使うIPv6に移行しつつあります。それでは、具体的にどれくらいの台数の機器を管理することができるのでしょうか。
IPv4 IPv6で表すことができるIpアドレスの数
- import math
- print(2**32)
- print(2**128)
- print(math.log10(2**128))
4294967296 340282366920938463463374607431768211456 38.53183944498959
2. 32ビットでは$2^{32}\fallingdotseq 42.9$憶通りの数字を表現することができます。かなり大きな数字ですが、世界の人口が100憶を超え、多くの人が携帯電話を持ち、家電までインターネットにつながる時代となると、これではとても足りません。
3. これに対し現在普及しつつあるIPv6では、$2^{128}\fallingdotseq 3.403 × 10^{38}$通りのアドレスを管理することができます。これは340澗2823溝6692穣0938予4634垓6337京4607兆4317億6821万1456になります。ちなにみに兆の1万倍が京(けい)、さらに垓(がい)、杼(じょ)、穣(じょう)溝(こう)澗(かん)となるので、とてつもなく大きな数字になります。世界中の人が1人で何台もの機器をインターネットにつないでも、全く問題ありません。Pythonはこのような大きな数値も難なく計算します。
桁数の大きな数の入力
桁数の多い数字を間違いなく入力するのは大変です。このとき、”,”(カンマ)ではなく”_”(アンダーバー)を使い3桁ごとに区切って入力することができます。
大きな桁数の表示
- ipv6 = 340_282_366_920_938_463_463_374_607_431_768_211_456
- print(ipv6)
- print(f'{ipv6:,}')
- print(f'{ipv6:_}')
340282366920938463463374607431768211456 340,282,366,920,938,463,463,374,607,431,768,211,456 340_282_366_920_938_463_463_374_607_431_768_211_456
1. 整数を“_”で区切って入力することができます。
2. 1.の場合も、コンピュータの内部では単純な整数として取り扱われます。
3. 整数をカンマ区切りで表示するときは、print関数にフォーマット済み文字列リテラルで書式’,’を指定します。
4. 3.と同様に、”_”で3桁ごとに区切る場合、フォーマット済み文字列リテラルで書式’_’を指定します。
整数型の変数のオブジェクトサイズ
変数がコンピュータの記憶装置上で占める場所の大きさを、その変数のオブジェクトサイズといいます。Pythonの整数型の変数のオブジェクトサイズが、桁数に応じてどのように変化するのか確認します。
$2^{30}-1$までは28バイト
コンピュータでは数字は2進数で把握します。整数型の変数のオブジェクトのサイズは、$\pm2^{30}-1$までの数値を代入した変数については、28バイト(1バイト=8ビットなので224ビット)になります。これに対し、$\pm2^{30}$になると32バイトと4バイト増えます。
整数型の変数の大きさ
- import sys
- z_list = [1, 2**30-1, 2**30, -1, -(2**30-1), -2**30]
- for z in z_list:
- print(sys.getsizeof(z), end=',')
- print(2**30)
28,28,32,28,28,32, 1073741823
2. $1$、$2^{30}-1$、$2^{30}$のプラス、マイナスの数字を要素とするリストをz_listとして定義します。
整数はドイツ語でZahlenというので、整数をzとして表すことがおおくあります。
5. 変数の大きさはsysモジュールのgetsizeof関数で調べることができます。このため、xの各要素にgetsizeof関数を適用し、結果を出力します。この結果、絶対値が1から$2^{30}-1$までは28バイト、これを超えると32バイトになることがわかります。
6. $2^{30}-1=1,073,741,823\fallingdotseq10.7$億なので、ほとんどの計算では28バイトで収まることになります。
$2^{30}$以上の場合
$2^{30}$以上の整数については、$2^{30}$倍ごとに4バイトずつ増えていきます。このことを次のプログラムで確認します。
大きな数字を代入したときの変数のサイズ
- import sys
- x=[2**30-1,2**30,2**60-1,2**60,2**90-1,2**90,2**120-1,2**120]
- for i in x:
- print(sys.getsizeof(i),end=',')
28,32,32,36,36,40,40,44,
$2^{30}$倍を単位にこれを1でも超えると4バイトずつ、枠が増えることがわかります。4バイトは32ビットですから、辻褄が合います。
エクセルとの比較
それでは我々がいつもお世話になっているエクセルではどうでしょうか?マイクロソフトのホームページによると、有効桁数は$10^{15}$とされています。
セルA1に14桁で1番大きな数字999兆9999億9999万9999-2を入力し、列幅を広げた上で整数表示にします。これに対し、数字を1ずつ足し算していくと、おかしなことが起こります。
セルA3の1000兆ぴったりまでは良いのですが、それに1を加えても1000兆とおなじ数字が表示されます。そして1000兆6になった時点で1000兆10となり、1の位で四捨五入されます(下1桁が5のときは切り下がっているので、JIS丸めによっているものと思われます)。おそらく我が国の事務処理の分野で1000兆円を超える数字を扱うのは、財務省で国債の残高を管理している部門くらいだと思います。この意味ではエクセルでも十分なような気もしますが、次のような計算をすると困ったことになります。1の位が1であるのは明らかなのに、1000兆を超えると0になってしまいます。
その点Pythonはいくらでも計算することができます。
Pythonでは整数型ではどんなに大きな数字も取り扱うことができる
- print(1111 * 1111)
- print(11111 * 11111)
- print(111111 * 111111)
- print(1111111 * 1111111)
- print(11111111 * 11111111)
- print(111111111 * 111111111)
- print(1111111111 * 1111111111)
- print(11111111111 * 11111111111)
- print(111111111111 * 111111111111)
1234321 123454321 12345654321 1234567654321 123456787654321 12345678987654321 1234567900987654321 123456790120987654321 12345679012320987654321
この計算では、8行目より後はあまり面白い結果にはなりませんが、Pythonの地味にすごいところを示してくれます。