数値型

概要

数値には「整数」「少数」などの様々な種類があります。 Pythonは数値の種類ごとに専用の型をもっていますが、 それぞれが連携して使えるように設計されているため「数値型」と一括りに捉えて利用することができます。

計算に使える演算子は整数でも少数でも共通であり、数値が表現できる範囲にも気を配る必要はありません。 また、数値関係の関数(たとえば絶対を求めるabs関数)も、整数と少数を区別する必要はありません。 区別する必要がある場合はキャストをすることで整数を少数にしたり、少数を整数にしたりします。

たし算や掛け算といった初等算数を理解していれば、数値型を使った計算は特に新しく覚えることはありません。 ただ、プログラミングに求められる独特の処理や、 基数(X進数)の仕組みや関数を使った変換手法の理解が必要になる場面がたまにあります。

数値型の特徴

Pythonの数値は整数を扱う「 整数型 」、少数を扱う「 浮動小数点型 」、 及び高等数学で利用されるいくつかの型(たとえば複素数型)からなりたっています。

C言語やJavaなどのプログラミング言語ではこれらの型の違いを正確に把握して、 状況に応じて使い分ける必要があります。 誤った使い方をすると「桁あふれ(型が使える数の範囲を超えてしまう)」といったトラブルが発生するためです。

一方、Pythonは整数型と浮動小数点型の利用方法に違いはなく、 桁あふれといった問題は発生しません。 そのため、金銭や科学で求められる厳密な計算でなければ、 計算の裏側の仕組みを理解する必要はありません。

複雑な計算が必要な場合は、そのためのパッケージやモジュールを使うことを検討すべきです。

数値型の基本操作

演算子を使った演算

数値計算で利用される演算子として以下があります。

| 利用可能な演算子 | 説明 | |:-------------:|:---:| | M + N | 足し算 | | M - N | 引き算 | | M * N | 掛け算 | | M / N | 割り算 | | M // N | 割り算(切り捨て) | | M % N | 剰余(あまり) | | M ** N | べき乗(M * M * M.. を N回) |

割り算には割合を求めるためのものと、余りを求めるものがあります。 通常は少数を返す可能性がある「割合を求めるための割り算」を使います。

>>> 5 / 2
2.5

>>> 5 // 2
2

割り算の余り(剰余)が必要な場合は「%」演算子を使います。

>>> 5 % 2
1

演算子の優先度は数値計算に関しては算数程度の理解で十分です。 具体的には「足し算引き算より、掛け算割り算が優先される」というものです。

複合代入演算子を使った演算

複合代入演算子を使うと、ある変数を使った演算をして、 その結果を変数に再度代入するということができます。

| 利用可能な演算子 | 説明 | |:-------------:|:---:| | M += N | M = M + N | | M -= N | M = M - N | | M *= N | M = M * N | | M /= N | M = M / N | | M %= N | M = M % N | | M = N | M = M N |

たし算の複合代入演算子以外はあまり利用されません。

単項演算子を使ったプラスマイナスの反転

マイナスの数値は「-5」というように、数値の隣にマイナス記号をつけます。 マイナスの数値を宣言で使うことはもちろん、そのまま計算に組み入れることもできます。

>>> a = -3

>>> 5 - -3
8

この数値に添えられた「-」の演算子は「 単項演算子 」と呼ばれており、 演算子の右のみにオペランドをとります。 そのため「単項」という名前がついています。 ブール演算で使われる「not」も単項演算子です。

数値計算に用いられる単項演算子には以下の2つがあります。

| 利用可能な演算子 | 説明 | |:-------------:|:---:| | - | ある値の正負を反転する | | + | ある値そのもの(なにもしない) |

これらの単項演算子は数値に直接添えるだけでなく、変数に添えることもできます。

>>> a = 5
>>> -a
-5

>>> +a
5

単項演算子の優先度は掛け算割り算よりも高いです。 そのため、「5 * -3」は「5 * (-3)」と解釈されています。

キャストを使った整数と少数の変換

特定の場面では整数か少数か分からない数値ではなく、 「整数が必要」「少数が必要」といった厳密な指定が必要になることがあります。

その場合はint関数を使った整数へのキャストと、 float関数を使った少数へのキャストを行います。 少数を整数にキャストすると、小数点は切り捨てられます。

>>> a = int(5.999)
>>> print(a)
5

>>> b = float(5)
>>> print(b)
5.0

数値に関わる組み込み関数

abs

引数として与えた整数もしくは少数の絶対値(0からの距離)を返します。

>>> a = abs(5)
>>> print(a)
5

>>> b = abs(-5.0)
>>> print(b)
5.0

divmod

割り算の商と余りを同時に求めたい場合はdivmod関数を使います。 商と余りをタプルでまとめて返します。

>>> divmod(5, 2)
(2, 1)

演算子「//」と「%」を使うことで商と余りを求めることができますが、 その場合は2回計算が必要です。 一方、divmodは1回の計算で両方を求められます。

max

複数与えることができる引数のなかで、最大値を返します。

>>> max(1, 5, 3)
5

もしくは引数で与えたリストやセットの要素の最大値を返します。

>>> max([1, 5, 3])
5

>>> max({1, 5, 3})
5

min

max関数と使い方は同じですが、最小値を返します。

>>> min(1, 5, 3)
1

>>> min([1, 5, 3])
1

pow

ある値XのY乗を求めるにはpow関数が使えます。

>>> pow(2, 8)
256

sum

リストやセットが持つ数値の合計値を得たい場合はsum関数を使います。

>>> sum([1,3,5])
9

基数

「0、1、2」と数が大きくなっていき、8、9となると次は桁があがって10になります。 このとき、ひとつの桁で表現できる数は0~9の10個であり、この1桁で表現できる数を「 基数 」と呼びます。 そしてその基数Nで表現される数え方を「N進数」と呼びます。 たとえば、0~9の10個であれば10進数、0~7の8個であれば8進数になります。

2進数と16進数

では、0~1で表現されるのは、基数が何で何進数と呼ばれているでしょうか。 基数が2なので、2進数です。コンピュータが理解可能なのは01だけという話を何度もしていますが、 要するにコンピュータは2進数を使うということです。

ただ、人間は01だけで構成された数字を見せられても、あまりピンときません。 たとえば、適当に打った01000100010011110010という2進数の大きさがどれほどなのか、一瞬では把握できません。 これを10進数に直すと279794になり、およそ28万であるということがわかります。

2進数を人が読みやすい10進数に変換するのは結構骨が折れます。 たとえば、01001101という2進数を10進数に変換するには、 2進数の各桁の値(0 or 1)に2 の“桁-1”乗をかけた値を足しあわせていくという処理を行います。 試しに低い桁から順に足しあわせて計算してみます。

(1 x 2^0) + (0 x 2^1) + (1 x 2^3) + (1 x 2^4) + (0 x 2^5) + (0 x 2^6) + (1 x 2^7) + (0 x 2^8)
 = 1 + 0 + 4 + 8 + 0 + 0 + 64 + 0
 = 77

# 補足
# N^MはNのM乗という意味。べき乗をテキストで表現できるので便利な書き方
# Python的に書くとN ** M
# 2^0 は1, 2^1は2, 2^2は4,……, 2^8は128

2進数 01001101 から 10進数の 77 を求められています。 疑い深い人は2進数から10進数に変換できるアプリケーションの電卓などもあるでしょうから、確認してみてもいいかもしれません。 0進数から2進数への変換はこの逆で、割り算を繰り返すようなことをします。

以上のように「2進数は桁が大きくなりわかりづらい」ものの「10進数は2進数と相性が悪い(変換しにくい)」という問題があるので、 コンピュータでは2進数と相性がよい16進数がよく使われます。 16進数は0~9までの数字だと16パターンを表現できないので、 アルファベットを使って、0から15までを1桁で表現します。 具体的には以下のようになります。

16進数 : 10進数
0  :  0
1  :  1
2  :  2

8  :  8
9  :  9
A  : 10
B  : 11
C  : 12
D  : 13
E  : 14
F  : 15
10 : 16   # 桁が増える
11 : 17

この16進数は2進数と非常に相性がよく、2進数の4桁をちょうど16進数だと1桁で表現できます。 0000~1111は10進数でいうと0~15なので、ちょうど16進数の0~Fにピッタリあてはまるのです。 1バイト(0から255)は8ビット、つまり2進数が8桁なので、ちょうど16進数2桁で表現できます。

基数の変換

基数変換に便利なPythonの関数を紹介します。10進数から2進数、8進数、16進数への変換は専用の関数を使います。

print(bin(100))  # 2進数
# 0b1100100

print(oct(100))  # 8進数
# 0144

print(hex(100))  # 16進数
# 0x64

先頭に何かついていますが、0bは2進数、0xは16進数という表明に使います。 8進数は0だけを先頭につけるというルールもありますが、桁埋めの0と混同しないように注意してください。

次に、N進数から10進数への変換です。実はこれはすでに使ったことがある関数 int を使います。

print(int('100'))
# 100

print(int('1100100', 2))  # 2進数
# 100

print(int('0144', 8))  # 8進数
# 100

print(int('64', 16))   # 16進数
# 100

print(int('6B', 16))   # A,B,C……も使える
# 107

print(int('212', 3))      # あまり使わないN進数も一応使える
# 23

intの第一引数に数字のもとになる文字列を入れ、第二引数に基数を指定します。 第二引数を省略すると10進数として扱われます。基数とN進数に関しては以上です。

基数の変換のプログラム

コメント: アルゴリズムの説明とサンプルコードを書くこと