ブログの説明

学校に通わないで学んだことを記しています。間違っているところが何かありましたらご指摘下さると幸いです。コメントに対する返信が遅れる可能性があります。その場合は申し訳ございません。

このブログでは広告を表示しています。このブログ内の投稿記事を検索するには右上の拡大鏡のアイコンを、アーカイブやラベル付けから投稿記事を閲覧するには左上の三重線のアイコンをクリックして下さい。

数式の表示にはMathJaxを利用させていただいています。数式の表示のためにJavaScriptが有効である必要があります。そうでない場合、訳の分からないLaTeXのコードが表示されます。幾何学図形やチャートの表示にはHTML5 CanvasやGoogle Chartを使用しています。その表示のためにもJavaScriptが有効である必要があります。

n進数と基数変換

10進数

0から9までの数字を使い、1から9まで数えたら位を1つ上げて(桁を1つ増やして)10にする数え方が一般に行われている。こうした数え方は10進法しんほうと呼ばれ、それらの数は10進数しんすうと呼ばれている。この数え方は、人が自分の手の指を使って物を数えるのに適していたため、そこから生まれたと考えらている。

0, 1, 2, 3, 4, 5, 6, 7, 8, 9まで数えたらその次が10となり、11, 12, ..., 19まで数えたらその次が20となり、99まで数えたらその次が100となり、999まで数えたらその次が1000となる。桁をこのように増やしてゆくことで限られた数字で無限の数を表現することができる。このような記数法は10進の位取くらいど記数法きすうほうと呼ばれている。

\begin{align*} 1 + 9 &= 10 \\ \vdots \\ 19 + 1 &= 20 \\ \vdots \\ 29 + 1 &= 30 \\ \vdots \\ 99 + 1 &= 100 \\ \vdots \\ 199 + 1 &= 200 \\ \vdots \\ 999 + 1 &= 1000 \\ \vdots \end{align*}

漢字で二千四百六十八という数は、一の位が8つで、十の位が6つで、百の位が4つで、千の位が2つであることを意味している。アラビア数字による位取り記数法では2468のように記され、漢字では記されていた千、百、十という各位を表す文字が記されない。しかし、例えば2468は\( 2 + 4 + 6 + 8 \)であることを意味しているわけではなく\( 2000 + 400 + 60 + 8 \)であることを意味している。

\[ 2468 \neq 2 + 4 + 6 + 8 \]
\begin{align*} 2468 &= 2000 + 400 + 60 + 8 \\ &= 2 \times 1000 + 4 \times 100 + 6 \times 10 + 8 \times 1 \\ &= 2 \times 10^3 + 4 \times 10^2 + 6 \times 10^1 + 8 \times 10^0 \end{align*}

\( \neq \)は等しくないという意味である。この二つ目の数式にある\( 10^3 = 1000,\ 10^2 = 100,\ 10^1 = 10,\ 10^0 = 1 \)が各桁の数字が属しているくらいであり、それらはそれぞれ千の位、百の位、十の位、一の位またはけたと呼ばれている。各位が持っている千、百、十、一という値を数学では桁値けたちと呼ぶが、計算機科学の世界では重みと呼ばれている。桁のそれぞれの数字はその桁値だけ倍にした数を表している。

2進数

電子計算機やコンピュータの内部では、電圧の高低差を利用した2進法による計算が行わている。2進法は0と1という2つの数字だけを使って表されている。2進法では、0, 1, 10, 11, 100, 101, 110, 111, 1000, ...のように桁が増えてゆく。これは2進の位取り記数法である。

\begin{align*} 1 + 1 &= 10 \\ 10 + 1 &= 11 \\ 11 + 1 &= 100 \\ 101 + 1 &= 110 \\ 110 + 1 &= 111 \\ 111 + 1 &= 1000 \\ \vdots \end{align*}

2進法では、10は「ジュー」と読むのではなく「イチゼロ」と読む。同様に11は「ジューイチ」ではなく「イチイチ」、100は「ヒャク」ではなく「イチゼロゼロ」、111は「イチイチイチ」と電話番号のように読む。

例えば、2進数の1101「イチイチゼロイチ」を多項式にして表せば、次のような数であることを意味している。

\begin{align*} 1101 &= 1 \times 10^3 + 1 \times 10^2 + 0 \times 10^1 + 1 \times 10^0 \\ &= 1 \times 1000 + 1 \times 100 + 0 \times 10 + 1 \times 1 \\ &= 1000 + 10 + 0 + 1 \end{align*}

ただし、2進法での桁値である例えば1000, 100, 10は、漢字でいうところの千、百、十を意味するのではない。2進数での1000は「イチゼロゼロゼロ」、100は「イチゼロゼロ」、10は「イチゼロ」という桁値を持っていることになる。

2進数の1桁は、計算機科学、情報数学、情報工学の分野ではビットという単位で呼ばれている。C言語などのプログラミング言語では1011BのようにBを添えて2進数であることを示す。Bは2進数を表す英語binary numberの頭文字bによる。

2進数を10進数への変換

桁値を理解することが10進数へと他の進数を変換するために役立つ。次の数式は2進数である1101をそれに対応する10進数へと変換している多項式である。ここでは\( = \)の代わりに\( \rightarrow \)という記号を使って2進数と10進数との間の対応関係を表している。下の式の計算結果から2進数の1101が10進数では13に対応していることが分かる。

\begin{align*} (1101)_2 & \rightarrow (1 \times 2^3 + 1 \times 2^2 + 0 \times 2^1 + 1 \times 2^0)_{10} \\ & \rightarrow (1 \times 8 + 1 \times 4 + 0 \times 2 + 1 \times 1)_{10} \\ & \rightarrow (1 \times 8 + 1 \times 4 + 0 + 1 \times 1)_{10} \\ & \rightarrow (8 + 4 + 0 + 1)_{10} \\ & \rightarrow (13)_{10} \end{align*}

上の数式では、\( \rightarrow \)の左辺が2進数であり、\( \rightarrow \)の右辺が10進数である。2進数であることを\( (...)_2 \)と表し、10進数であることを\( (...)_{10} \)と表している。2進数である1101は10進数では13に対応している。2進数のそれぞれの位の重み、すなわち桁値を10進数で表すと、\( 2^3 = 8,\ 2^2 = 4,\ 2^1 = 2,\ 2^0 = 1\)になることが分かる。2進数でのそれぞれの桁が10進数ではこのような重みを持っていることを理解していれば、2進数から10進数への変換は簡単な算術でたやすく行える。

2進数と10進数の対応表

次の表は2進数と10進数の対応関係を示している。この表から2進数の1101が10進数の13に対応することが見て取れる。

2進数と10進数の対応関係
2進数 10進数
0 0
1 1
10 2
11 3
100 4
101 5
110 6
111 7
1000 8
1001 9
1010 10
1011 11
1100 12
1101 13
1110 14
1111 15
10000 16
10001 17
10010 18
10011 19
10100 20
10101 21
10110 22
10111 23
11000 24
11001 25
11010 26
11011 27
11100 28
11101 29
11110 30
11111 31
100000 32
100001 33
100010 34
100011 35
100100 36
100101 37
100110 38
100111 39
101000 40
101001 41
101010 42
101011 43
101100 44
101101 45
101110 46
101111 47
110000 48
110001 49
110010 50
110011 51
110100 52
110101 53
110110 54
110111 55
111000 56
111001 57
111010 58
111011 59
111100 60
111101 61
111110 62
111111 63
1000000 64
1000001 65
1000010 66
1000011 67
1000100 68
1000101 69
1000110 70
1000111 71
1001000 72
1001001 73
1001010 74
1001011 75
1001100 76
1001101 77
1001110 78
1001111 79
1010000 80
1010001 81
1010010 82
1010011 83
1010100 84
1010101 85
1010110 86
1010111 87
1011000 88
1011001 89
1011010 90
1011011 91
1011100 92
1011101 93
1011110 94
1011111 95
1100000 96
1100001 97
1100010 98
1100011 99
1100100 100
1100101 101
1100110 102
1100111 103
1101000 104
1101001 105
1101010 106
1101011 107
1101100 108
1101101 109
1101110 110
1101111 111
1110000 112
1110001 113
1110010 114
1110011 115
1110100 116
1110101 117
1110110 118
1110111 119
1111000 120
1111001 121
1111010 122
1111011 123
1111100 124
1111101 125
1111110 126
1111111 127
10000000 128

上の表においてもう一つ注目すべき点は、この表から2進数の桁値を10進数で表したときの値が見て取れることである。2進数の1が10進数では1、2進数の10が10進数では2、2進数の100が10進数では4、2進数の1000が10進数では8になっている。2進数で桁が増えているところでの10進数の値を見れば、2進数のそれぞれの位を10進数で表した場合の桁値が判断できる。その対応関係は次の表の通りになる。

2進数の位を10進数での桁値で表すと
2進数 10進数 10進冪乗
1 1 \( 2^0 \)
10 2 \( 2^1 \)
100 4 \( 2^2 \)
1000 8 \( 2^3 \)
10000 16 \( 2^4 \)
100000 32 \( 2^5 \)
1000000 64 \( 2^6 \)
10000000 128 \( 2^7 \)

2進数で位が増えたところの10進数での値を見ると、2進数の各位の重み(桁値)を10進数で表した値が直前の数の2倍ずつ増えていることが、この表から見て取れる。これは初項しょこうが1、公比こうひが2の等比数列である。初項は最初の数、公比の2はこの数列が常に2倍ずつ増えていることによる。

\[ \begin{array}{c} & 1 & 2 & 4 & 8 & 16 & 32 & 64 & 128 & ... \\ & 2^0 & 2^1 & 2^2 & 2^3 & 2^4 & 2^5 & 2^6 & 2^7 & ... \end{array} \]

冪乗べきじょうで表したとき、全ての桁値に共通する2の数字は基底きていまたは単にそこと呼ばれている。計算機科学ではこれを基数きすうと呼ぶことが多いが、数学でいう集合数のことではない。英語ではbaseまたはradix。2進数の2はここから来ている。10進数は10を基底とする進法である。さらに、等比数列の特徴として、基数の右上の指数しすうが0から順に0, 1, 2, 3, 4, 5, ...と増えていることがこの表から見て取れる。

ちなみに、\( a = b^i \)と表されるとき、指数の形で表されているこのiの値はbを基底とするaの値の対数たいすうとも呼ばれている。例えば\( 2^7 \)の指数7は2を基底とする128の対数と呼び、\( 2^5 \)の指数5は2を基底とする32の対数と呼ぶ。それぞれ次のように書く。

\[ \log_2 128 = 7,\ \log_2 32 = 5 \]

冪乗に関するちょっとした注意

冪乗べきじょう基底部きていぶ指数部しすうぶから成っている。基底部の数を\( r \)としたとき、冪乗とは次のような演算を簡略に表記したものである。ちなみにrは基数を意味するradixの頭文字。

\begin{align*} r^2 &= r \times r \\ r^4 &= r \times r \times r \times r \end{align*}

ただし、\( r \)の0乗と\( r \)の1乗はそれぞれ次のようになることに注意が必要である。

\begin{align*} r^0 &= 1 \\ r^1 &= r \end{align*}

なぜなら、冪乗は厳密には次のような演算を意味するからである。

\begin{align*} r^0 &= 1 \\ r^1 &= 1 \times r = r \\ r^2 &= 1 \times r \times r \\ r^3 &= 1 \times r \times r \times r \\ r^4 &= 1 \times r \times r \times r \times r \end{align*}

累乗るいじょうと冪乗の違いは累乗の指数部が0を含まない自然数に限られること。冪乗には指数部が小数や分数である分数乗や指数部が円周率である無理数乗までもが含まれる。冪乗は累乗を拡張したものだと言えるのかもしれない。

8進数や12進数を10進数へと変換

例えば8進法や12進数でも同様のことが成り立つ。8進法は0から7までの数字で表す位取り記数法であり、12進法は0から9、そしてTとEまでの英数字で表す位取り記数法である。TはtenのTで10進数で10に対応し、EはelevenのEで10進数で11に対応する。

2進数の場合と同様の方法で8進数や12進数を10進数へと変換することができる。ここでは\( (...)_r \)という形でr進数であることを示す。rはradixのrで、rには任意の自然数しぜんすうが入る。ここでは例として8進数と12進数を表すので、それぞれのrに8と12が入っている。

\begin{align*} (2308)_8 & \rightarrow (2 \times 8^3 + 3 \times 8^2 + 0 \times 8^1 + 8 \times 8^0)_{10} \\ & \rightarrow (2 \times 512 + 3 \times 64 + 0 \times 8 + 8 \times 1)_{10} \\ & \rightarrow (1024 + 192 + 0 + 8)_{10} \\ & \rightarrow (1216 + 8)_{10} \\ & \rightarrow (1224)_{10} \end{align*}
\begin{align*} (3TE)_{12} & \rightarrow (3 \times 12^2 + 10 \times 12^1 + 11 \times 12^0)_{10} \\ & \rightarrow (3 \times 144 + 10 \times 12 + 11 \times 1)_{10} \\ & \rightarrow (432 + 120 + 11)_{10} \\ & \rightarrow (552 + 11)_{10} \\ & \rightarrow (563)_{10} \\ \end{align*}

これらの計算のとおり、、8進数の2308を10進数に変換すると10進数の1224になり、12進数の3TEを10進数に変換すると10進数の563になることが分かる。

8進数と12進数の桁値は次のような対応表になる。

8進数の位を10進数での桁値で表すと
8進数 10進数 10進冪乗 10進対数
1 1 \( 8^0 \) 0
10 8 \( 8^1 \) 1
100 64 \( 8^2 \) 2
1000 512 \( 8^3 \) 3
10000 4096 \( 8^4 \) 4
100000 32768 \( 8^5 \) 5
1000000 262144 \( 8^6 \) 6
10000000 2097152 \( 8^7 \) 7
100000000 16777216 \( 8^8 \) 8

12進数の位を10進数での桁値で表すと
12進数 10進数 10進冪乗 10進対数
1 1 \( 12^0 \) 0
10 12 \( 12^1 \) 1
100 144 \( 12^2 \) 2
1000 1728 \( 12^3 \) 3
10000 20736 \( 12^4 \) 4
100000 248832 \( 12^5 \) 5
1000000 2985984 \( 12^6 \) 6
10000000 35831808 \( 12^7 \) 7
100000000 429981696 \( 12^8 \) 8

小数の場合

小数ではどうか。例えば10進数の小数0.123は次のような多項式に表すことができる。マイナスの指数を持つ冪乗は小数を表している。

\begin{align*} 0.123 &= 0.1 + 0.02 + 0.003 \\ &= \dfrac{1}{10} + \dfrac{2}{100} + \dfrac{3}{1000} \\ &= 1 \times 0.1 + 2 \times 0.01 + 3 \times 0.001 \\ &= 1 \times \dfrac{1}{10} + 2 \times \dfrac{1}{100} + 3 \times \dfrac{1}{1000} \\ &= 1 \times \dfrac{1}{10} + 2 \times \dfrac{1}{10^2} + 3 \times \dfrac{1}{10^3} \\ &= 1 \times 10^{-1} + 2 \times 10^{-2} + 3 \times 10^{-3} \end{align*}

10進数の整数+小数の数75.29を多項式に表すと次のようになる。

\begin{align*} 75.29 &= 70 + 5 + 0.2 + 0.09 \\ &= 7 \times 10 + 5 \times 1 + 2 \times 0.1 + 9 \times 0.01 \\ &= 7 \times 10 + 5 \times 1 + 2 \times \dfrac{1}{10} + 9 \times \dfrac{1}{100} \\ &= 7 \times 10 + 5 \times 1 + 2 \times \dfrac{1}{10^1} + 9 \times \dfrac{1}{10^2} \\ &= 7 \times 10^1 + 5 \times 10^0 + 2 \times 10^{-1} + 9 \times 10^{-2} \end{align*}

したがって、2進数の小数0.101を10進数に変換するには次のように計算すればよい。2進数の各桁値を10進数の冪乗で表したとき、基底の数(基数)は10ではなく2になる。この計算結果から、2進数の0.101は10進数では0.625だと分かる。

\begin{align*} (0.101)_2 & \rightarrow (1 \times 2^{-1} + 0 \times 2^{-2} + 1 \times 2^{-3})_{10} \\ & \rightarrow \left(1 \times \dfrac{1}{2} + 0 \times \dfrac{1}{2^2} + 1 \times \dfrac{1}{2^3} \right)_{10} \\ & \rightarrow (1 \times 0.5 + 0 \times 0.25 + 1 \times 0.125)_{10} \\ & \rightarrow (0.5 + 0 + 0.125)_{10} \\ & \rightarrow (0.625)_{10} \end{align*}

2進数の小数の各桁値を表にしてみるとこうなる。

2進小数の各位の10進数での桁値
2進数 10進数 10進冪乗 10進分数 10進対数
0.1 0.5 \( 2^{-1} = 0.5^1 \) \( \dfrac{1}{2^1} \) -1
0.01 0.25 \( 2^{-2} = 0.5^2 \) \( \dfrac{1}{2^2} \) -2
0.001 0.125 \( 2^{-3} = 0.5^3 \) \( \dfrac{1}{2^3} \) -3
0.0001 0.0625 \( 2^{-4} = 0.5^4 \) \( \dfrac{1}{2^4} \) -4
0.00001 0.03125 \( 2^{-5} = 0.5^5 \) \( \dfrac{1}{2^5} \) -5
0.000001 0.015625 \( 2^{-6} = 0.5^6 \) \( \dfrac{1}{2^6} \) -6
0.0000001 0.0078125 \( 2^{-7} = 0.5^7 \) \( \dfrac{1}{2^7} \) -7
0.00000001 0.00390625 \( 2^{-8} = 0.5^8 \) \( \dfrac{1}{2^8} \) -8

マイナスの指数を持つ冪乗

\( r \)のマイナス\( i \)乗は次のような意味を表している。\( = \)は左右が互いに等しいことを示す。\( r \)は基底を意味する英語radix――base of numberとも言う――のr、\( i \)は指数を意味する英語indexのi。

\[ r^{-i} = \dfrac{1}{r^i} = 1 \div r^i \]

\( i \)に具体的な数を代入だいにゅうして表すとこうなる。

\begin{align*} r^{-1} &= \dfrac{1}{r} = 1 \div r \\ r^{-2} &= \dfrac{1}{r^2} = 1 \div r^2 \\ r^{-3} &= \dfrac{1}{r^3} = 1 \div r^3 \\ r^{-4} &= \dfrac{1}{r^4} = 1 \div r^4 \\ r^{-5} &= \dfrac{1}{r^5} = 1 \div r^5 \\ r^{-6} &= \dfrac{1}{r^6} = 1 \div r^6 \\ r^{-7} &= \dfrac{1}{r^7} = 1 \div r^7 \\ & \hspace{2em} \vdots \end{align*}

指数部がマイナスになっている冪乗は、1以下0以上の数、すなわち小数を表している。

r進数から10進数への変換

r進数からその数に対応する10進数への数の変換は、一般に次のようにして計算することができる。見やすくするために各位の計算を表している各項を括弧かっこでくくった。

\begin{align*} I_n \rightarrow \sum_{i=0}^{n-1} (a_i \times r^{i}) &= (a_0 \times r^0) + (a_1 \times r^1) + (a_2 \times r^2) + ... + (a_n \times r^{n-1}) \end{align*}

\( I_n \)のIは整数を表す英語integerの頭文字、添え字のnは桁数を表す。\( r \)とは基底を表す英語radixの頭文字かしらもじであり、2進数の場合は2、5進数の場合は5が入る。その添え字のnは与えられた数の桁数を表している。\( \sum \)はサメーション、つまり合計のことであり、ギリシア文字でシグマと読む。\( a \)は与えられた数の各位にある数字、\( n \)は与えられた数の桁の数のことで、0から数えるので\( n \)から1を引いてある。\( k \)は桁値を冪乗で表したときの指数を表し、低い位から何桁目かを指している。サメーションの下の\( k=0 \)は0から始まることを表し、サメーションの上の\( n \)(任意の自然数)はその数の桁数回足し算が続くことを意味している。足し算なので交換法則こうかんほうそく、すなわち足す順番が自由でよいという法則が成り立ち、計算の順番を逆にしても同じ値が得られる。

小数の場合は次のようになる。

\begin{align*} \sum_{j=1}^{m} (a_{-j} \times r^{-j}) &= (a_{-1} \times r^{-1}) + (a_{-2} \times r^{-2}) + (a_{-3} \times r^{-3}) + ... + (a_{-m} \times r^{-m}) \\ &= \left(a_{-1} \times \dfrac{1}{r} \right) + \left(a_{-2} \times \dfrac{1}{r^2} \right) + \left(a_{-3} \times \dfrac{1}{r^3} \right) + ... + \left(a_{-m} \times \dfrac{1}{r^m} \right) \end{align*}

整数部と小数部を両方持つ数の場合はこう一般化できる。

\[ \sum_{i=0}^{n-1} (a_i \times r^{i}) + \sum_{j=1}^{m} (a_{-j} \times r^{-j}) \]

数学の文字式では普通、掛け算の演算記号\( \times \)または\( \cdot \)を省略するので次のように書ける。

\begin{align*} \sum_{i=0}^{n-1} a_i r^{i} &= a_0 r^0 + a_1 r^1 + a_2 r^2 + ... + a_n r^{n-1} \end{align*}
\begin{align*} \sum_{j=1}^{m} a_{-j} r^{-j} &= a_{-1} r^{-1} + a_{-2} r^{-2} + a_{-3} r^{-3} + \dots + a_{-m} r^{-m} \\ &= a_{-1} \dfrac{1}{r} + a_{-2} \dfrac{1}{r^2} + a_{-3} \dfrac{1}{r^3} + \dots + a_{-m} \dfrac{1}{r^m} \end{align*}

整数部と小数部を両方持つ数の場合は次のとおり。

\[ \sum_{i=0}^{n-1} a_i r^{i} + \sum_{j=1}^{m} a_{-j} r^{-j} = \sum_{k=-m}^{n-1} a_k r^k \]

数学記号と数式で表現するとなんだか難しく見えてしまうけれども、その変換規則は各桁を表す定数(係数)にr進数の基数の冪乗を掛けてそれらの値の合計を求める式だから簡単。

ちなみに、この文字式は多項式のように見えるが、小数部の変数rの指数に正数でなく負数が使われているために通常の多項式の条件を満たさない。したがって通常の多項式とは区別されてローラン多項式と呼ばれている。

\[ \begin{array}{r:l} i & \text{番号を表す変数} \\ i = 1 & \text{下限値} \\ n & \text{上限値} \\ a_i & \text{i番目の係数(定数)} \\ r^{-i} & \text{負数の指数を持つ変数} \\ \end{array} \] \[ \sum_{i=1}^n a_i r^{-i} \]

したがって位取り記数法によって表された数値は、整数部は多項式として展開できるが、小数部はローラン多項式として展開できる。

あるr進数から別のr進数への変換は基数変換きすうへんかんと呼ばれている。

16進数

計算機科学の中では、2進数を人がより扱いやすくするために16進数を用いて表すことが多い。16進数の表記にはアラビア数字の0〜9とローマ字の大文字A〜Fか小文字a〜fが使われている。

2/4/8/16進数と10進数の対応関係
2進数 4進数 8進数 16進数 10進数
0 0 0 0 0
1 1 1 1 1
10 2 2 2 2
11 3 3 3 3
100 10 4 4 4
101 11 5 5 5
110 12 6 6 6
111 13 7 7 7
1000 20 10 8 8
1001 21 11 9 9
1010 22 12 A 10
1011 23 13 B 11
1100 30 14 C 12
1101 31 15 D 13
1110 32 16 E 14
1111 33 17 F 15
10000 40 20 10 16
10001 41 21 11 17
10010 42 22 12 18
10011 43 23 13 19
10100 50 24 14 20
10101 51 25 15 21
10110 52 26 16 22
10111 53 27 17 23
11000 60 30 18 24
11001 61 31 19 25
11010 62 32 1A 26
11011 63 33 1B 27
11100 70 34 1C 28
11101 71 35 1D 29
11110 72 36 1E 30
11111 73 37 1F 31
100000 80 40 20 32

16進数を10進数へ基数変換

例えば16進数の数8C1を10進数へと基数変換してみる。16進数なので基底16、8C1なので3桁。これらを先程の公式\( \sum_{i=0}^{n-1} x_i r^{i} \)の変数\( r \)と\( n \)にそれぞれ代入すると、\( r = 16 \)、\( n = 3 \)となる。16進数のCは10進数では12に当たるので12として計算する。したがって次のように計算することができる。この計算結果から、16進数の8C1が10進数では2257に対応することが分かる。

\begin{align*} (8C1)_{16} & \rightarrow (1 \times 16^0 + 12 \times 16^1 + 8 \times 16^2)_{10} \\ & \rightarrow (1 \times 1 + 12 \times 16 + 8 \times 256)_{10} \\ & \rightarrow (1 + 192 + 2048)_{10} \\ & \rightarrow (193 + 2048)_{10} \\ & \rightarrow (2241)_{10} \end{align*}

小数点を持つ16進数の2F.5Aを10進数に基数変換するには、次のように計算することができる。16進数のFは10進数では15、16進数のAは10進数では10なので、その数に置き換えて計算する。

\begin{align*} (2F.5A)_{16} & \rightarrow (2 \times 16^1 + 15 \times 16^0 + 5 \times 16^{-1} + 10 \times 16^{-2})_{10} \\ & \rightarrow \left(2 \times 16 + 15 \times 1 + 5 \times \dfrac{1}{16} + 10 \times \dfrac{1}{16^2} \right)_{10} \\ & \rightarrow \left(32 + 15 + 5 \times 0.0625 + 10 \times \dfrac{1}{256} \right)_{10} \\ & \rightarrow (47 + 0.3125 + 10 \times 0.00390625)_{10} \\ & \rightarrow (47.3125 + 0.0390625)_{10} \\ & \rightarrow (47.3515625)_{10} \end{align*}
16進数の位を10進数での桁値で表すと
16進数 10進数 10進冪乗 10進対数
0.0001 0.00001525879 \( 16^{-4} \) -4
0.001 0.0002441406 \( 16^{-3} \) -3
0.01 0.00390625 \( 16^{-2} \) -2
0.1 0.0625 \( 16^{-1} \) -1
1 1 \( 16^0 \) 0
10 16 \( 16^1 \) 1
100 256 \( 16^2 \) 2
1000 4096 \( 16^3 \) 3
10000 65536 \( 16^4 \) 4
100000 1048576 \( 16^5 \) 5
1000000 16777216 \( 16^6 \) 6
10000000 268435456 \( 16^7 \) 7
100000000 4294967296 \( 16^8 \) 8

10進数から16進数への基数変換

上の二つの計算が正しかったかどうか検算けんざんするために10進数から16進数への基数変換をしてみる。

10進数からr進数への基数変換には剰余演算を用いることができる。剰余演算は計算機科学ではモジュロ演算とも呼ばれている。

10進数の数を変換したい16進数の基数(基底)である16で割っていき、答が0になるまで繰り返せば、それらの余りが対応する16進数の各桁の値になる。この計算から10進数の2241は16進数の8C1に対応することが分かる。この計算法は連続除法や剰余法と呼ばれることがある。

\begin{align*} (2241 \div 16 \rightarrow \colorbox{yellow}{140} \text{ 余り} \colorbox{cyan}{1})_{10} & \rightarrow (\colorbox{cyan}{1} \times 1 = \colorbox{lime}{1})_{16} \\ (\colorbox{yellow}{140} \div 16 \rightarrow \colorbox{yellow}{8} \text{ 余り} \colorbox{cyan}{12})_{10} & \rightarrow (\colorbox{cyan}{C} \times 10 = \colorbox{lime}{C0})_{16} \\ (\colorbox{yellow}{8} \div 16 \rightarrow 0 \text{ 余り} \colorbox{cyan}{8})_{10} & \rightarrow (\colorbox{cyan}{8} \times 100 = \colorbox{lime}{800})_{16} \end{align*} \[ \therefore (2241)_{10} \rightarrow (\colorbox{lime}{1} + \colorbox{lime}{C0} + \colorbox{lime}{800} = 8C1)_{16} \]

上の式ではちょっとわかりにくいので計算の手続きを筆算風の表にしてみた。最初の余りが16進数の1の位に、2番目の余りが16進数の10の位に、3番目の余りが16進数の100の位に、それぞれ対応している。

\[ \begin{array}{r|l:l} \text{割る数} & \text{割られる数} & \text{余り} \\ 16 & 2241 & \\ \hline 16 & 140 & 1 \\ \hline 16 & 8 & 12 \rightarrow C \\ \hline & 0 & 8 \end{array} \] \[ \therefore (8C1)_{16} \]

次に、10進数の47.3515625を16進数に基数変換する。この場合、整数部と小数部を分けて考え、それぞれ別の方法で求める。整数部は16進数の基底である16で割る計算を繰り返し、それぞれの余りの値が16進数に変換したときの各桁の値になる。

小数部は逆に16を掛ける計算をする。その答えから整数部を取り除いた値にさらに16を掛ける。そしてその計算を繰り返す。答えの値から小数部がなくなれば計算を終了。それらの答えの整数部の値が16進数に変換したときの各桁の値になる。桁の並べ方が整数部とは逆順(上から下へ)になるので要注意。

まずは整数部から。10進数の15は16進数ではF。整数部は16進数で2Fと求まる。

\begin{align*} (47 \div 16 = \colorbox{yellow}{2} \text{ 余り} \colorbox{cyan}{15})_{10} & \rightarrow (\colorbox{cyan}{F} \times 1 = \colorbox{lime}{F})_{16}\} \\ (\colorbox{yellow}{2} \div 16 = 0 \text{ 余り} \colorbox{cyan}{2})_{10} & \rightarrow (\colorbox{cyan}{2} \times 10 = \colorbox{lime}{20})_{16} \end{align*} \[ \therefore (47)_{10} \rightarrow (\colorbox{lime}{F} + \colorbox{lime}{20} = 2F)_{16} \]

筆算風の表にして表すと次のように計算できる。

\[ \begin{array}{r|l:l} \text{割る数} & \text{割られる数} & \text{余り} \\ \hline 16 & 47 & \\ \hline 16 & 2 & 15 \rightarrow F \\ \hline & 0 & 2 \end{array} \] \[ \therefore (2F)_{16} \]

そして小数部。10進数の10は16進数ではA。小数部は16進数でA5と求まる。

\begin{align*} (0.3515625 \times 16 = \colorbox{cyan}{5}\colorbox{yellow}{.625})_{10} & \rightarrow (\colorbox{cyan}{5} \times \dfrac{1}{16^1} = \colorbox{lime}{0.5})_{16} \\ (\colorbox{yellow}{0.625} \times 16 = \colorbox{cyan}{10}.0)_{10} & \rightarrow (\colorbox{cyan}{10} \times \dfrac{1}{16^2} = \colorbox{lime}{0.0A})_{16} \end{align*} \[ \therefore (0.3515625)_{10} \rightarrow (\colorbox{lime}{0.5} + \colorbox{lime}{0.0A} = 0.5A)_{16} \]

筆算風の表で表すと次のようになる。

\[ \begin{array}{r|l:l} 掛ける数 & 掛けられる数 & 差し引いた整数部 \\ \hline 16 & 0.3515625 \\ \hline 16 & 0.625 & 5 \\ \hline 16 & 0 & 10 \rightarrow A \end{array} \] \[ \therefore (0.5A)_{16} \]

整数部の計算結果と小数部の計算結果を足し合わせると、16進数の2F.A5が求まることが分かる。

\[ \therefore (2F + 0.5A = 2F.5A)_{16} \]

10進数から2進数への基数変換

10進数から2進数への基数変換も、整数部、小数部ともに同様の方法で計算することができる。例えば、10進数の87.53を2進数に基数変換するには、次のように計算する。整数部と小数部でそれぞれ別々の計算方法を用いる。

10進数の整数部を変換したい2進数の基底数である2で割り、その答えを更に2で割る。この計算を答えが0になるまで繰り返す。このときの余りの値は0か1のいずれかになる。それらの余りの値を小さい桁から順番に並べれば2進数へと変換した整数部の値になる。

10進数の小数部には変換したい2進数の基底数である2を掛け、その答えの小数部だけを取り出し、その小数に更に2を掛ける。この計算を答えが整数部だけになるまで繰り返す。掛け算の各計算の答えの整数部は0か1のいずれかになる。この整数部を大きい桁から順番に並べていけば2進数へと変換された小数部になる。最後に整数部と小数部を足しあわせれば計算が完了する。

\begin{align*} (87 \div 2 \rightarrow \colorbox{yellow}{43} \text{ 余り} \colorbox{cyan}{1})_{10} & \rightarrow (\colorbox{cyan}{1} \times 10^0 = \colorbox{lime}{1})_2 \\ (\colorbox{yellow}{43} \div 2 \rightarrow \colorbox{yellow}{21} \text{ 余り} \colorbox{cyan}{1})_{10} & \rightarrow (\colorbox{cyan}{1} \times 10^1 = \colorbox{lime}{10})_2 \\ (\colorbox{yellow}{21} \div 2 \rightarrow \colorbox{yellow}{10} \text{ 余り} \colorbox{cyan}{1})_{10} & \rightarrow (\colorbox{cyan}{1} \times 10^2 = \colorbox{lime}{100})_2 \\ (\colorbox{yellow}{10} \div 2 \rightarrow \colorbox{yellow}{5} \text{ 余り} \colorbox{cyan}{0})_{10} & \rightarrow (\colorbox{cyan}{0} \times 10^3 = 0)_2 \\ (\colorbox{yellow}{5} \div 2 \rightarrow \colorbox{yellow}{2} \text{ 余り} \colorbox{cyan}{1})_{10} & \rightarrow (\colorbox{cyan}{1} \times 10^4 = \colorbox{lime}{10000})_2 \\ (\colorbox{yellow}{2} \div 2 \rightarrow \colorbox{yellow}{1} \text{ 余り} \colorbox{cyan}{0})_{10} & \rightarrow (\colorbox{cyan}{0} \times 10^5 = 0)_2 \\ (\colorbox{yellow}{1} \div 2 \rightarrow 0 \text{ 余り} \colorbox{cyan}{1})_{10} & \rightarrow (\colorbox{cyan}{1} \times 10^6 = \colorbox{lime}{1000000})_2 \end{align*} \[ \therefore (87)_{10} \rightarrow (\colorbox{lime}{1} + \colorbox{lime}{10} + \colorbox{lime}{100} + \colorbox{lime}{10000} + \colorbox{lime}{1000000} = 1010111)_2 \]

筆算風に表すと次のように書ける。

\[ \begin{array}{r|l:l} \text{割る数} & \text{割られる数} & \text{余り} \\ \hline 2 & 87 \\ \hline 2 & 43 & 1 \\ \hline 2 & 21 & 1 \\ \hline 2 & 10 & 1 \\ \hline 2 & 5 & 0 \\ \hline 2 & 2 & 1 \\ \hline 2 & 1 & 0 \\ \hline & 0 & 1 \end{array} \] \[ \therefore (1010111)_{2} \]

次は小数部の計算。

\begin{align*} (0.53 \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.06})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^1 = \colorbox{lime}{0.1})_2 \\ (\colorbox{yellow}{0.06} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.12})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^2 = 0)_2 \\ (\colorbox{yellow}{0.12} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.24})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^3 = 0)_2 \\ (\colorbox{yellow}{0.24} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.48})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^4 = 0)_2 \\ (\colorbox{yellow}{0.48} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.96})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^5 = 0)_2 \\ (\colorbox{yellow}{0.96} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.92})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^6 = \colorbox{lime}{0.00001})_2 \\ (\colorbox{yellow}{0.92} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.84})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^7 = \colorbox{lime}{0.000001})_2 \\ (\colorbox{yellow}{0.84} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.68})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^8 = \colorbox{lime}{0.0000001})_2 \\ (\colorbox{yellow}{0.68} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.36})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^9 = \colorbox{lime}{0.00000001})_2 \\ (\colorbox{yellow}{0.36} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.72})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^{10} = 0)_2 \\ (\colorbox{yellow}{0.72} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.44})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^{11} = \colorbox{lime}{0.0000000001})_2 \\ (\colorbox{yellow}{0.44} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.88})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^{12} = 0)_2 \\ (\colorbox{yellow}{0.88} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.76})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^{13} = \colorbox{lime}{0.000000000001})_2 \\ (\colorbox{yellow}{0.76} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.52})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^{14} = \colorbox{lime}{0.0000000000001})_2 \\ (\colorbox{yellow}{0.52} \times 2 = \colorbox{cyan}{1}\colorbox{yellow}{.04})_{10} & \rightarrow (\colorbox{cyan}{1} \times 0.1^{15} = \colorbox{lime}{0.00000000000001})_2 \\ (\colorbox{yellow}{0.04} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.08})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^{16} = 0)_2 \\ (\colorbox{yellow}{0.08} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.16})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^{17} = 0)_2 \\ (\colorbox{yellow}{0.16} \times 2 = \colorbox{cyan}{0}\colorbox{yellow}{.32})_{10} & \rightarrow (\colorbox{cyan}{0} \times 0.1^{18} = 0)_2 \\ & \vdots & \end{align*} \begin{align*} \therefore (0.53)_{10} & \rightarrow (\colorbox{lime}{0.1} + \colorbox{lime}{0.00001} \\ & + \colorbox{lime}{0.000001} + \colorbox{lime}{0.0000001} \\ & + \colorbox{lime}{0.0000000001} + \colorbox{lime}{0.000000000001} \\ & + \colorbox{lime}{0.0000000000001} + \colorbox{lime}{0.000000000000001} \\ & + \cdots = 0.100001111010111000...)_{2} \end{align*}

筆算表を使うと次のようになる。

\[ \begin{array}{r|l:l} 掛ける数 & 掛けられる数 & 差し引いた整数部 \\ \hline 2 & 0.53 \\ \hline 2 & 0.06 & 1 \\ \hline 2 & 0.12 & 0 \\ \hline 2 & 0.24 & 0 \\ \hline 2 & 0.48 & 0 \\ \hline 2 & 0.96 & 0 \\ \hline 2 & 0.92 & 1 \\ \hline 2 & 0.84 & 1 \\ \hline 2 & 0.68 & 1 \\ \hline 2 & 0.36 & 1 \\ \hline 2 & 0.72 & 0 \\ \hline 2 & 0.44 & 1 \\ \hline 2 & 0.88 & 0 \\ \hline 2 & 0.76 & 1 \\ \hline 2 & 0.52 & 1 \\ \hline 2 & 0.04 & 1 \\ \hline 2 & 0.08 & 0 \\ \hline 2 & 0.16 & 0 \\ \hline 2 & 0.32 & 0 \\ \hline \vdots & \vdots & \vdots \end{array} \] \[ \therefore (0.100001111010111000 \dots)_2 \]

この場合、小数部は計算を繰り返しても繰り返しても答えの小数部が0にならず、おそらくは無限に続く小数になってしまう。そうした場合は途中で中断するよりほかない。

最後に整数部と小数部を足し合わせる。

\begin{align*} \therefore (87.53)_{10} & \rightarrow (1010111 + 0.100001111010111000... \\ &= 1010111.100001111010111000...)_{2} \end{align*}

10進数からr進数への基数変換のアルゴリズム

整数部については一般に次のように求めることができる。xが変換元である10進数の任意の整数、rが変換先の数の基数、yが商、aが余り。

\begin{align*} (x \div r = y_1\ \mathrm{余り} a_1)_{10} & \rightarrow (1 \times a_1)_r \\ (y_1 \div r = y_2\ \mathrm{余り} a_2)_{10} & \rightarrow (10 \times a_2)_r \\ (y_2 \div r = y_3\ \mathrm{余り} a_3)_{10} & \rightarrow (100 \times a_3)_r \\ (y_3 \div r = y_4\ \mathrm{余り} a_4)_{10} & \rightarrow (1000 \times a_4)_r \\ & \vdots \\ (y_n \div r = 0\ \mathrm{余り} a_n)_{10} & \rightarrow (10^m \times a_n)_r \end{align*} \[ \therefore (10^m \times a_n + \dots + 100 \times a_3 + 10 \times a_2 + 1 \times a_1)_r \]

代数的な表し方をすると次のようになる。

\begin{align*} (x = ry_1 + a_1)_{10} & \rightarrow (10^0 \cdot a_1)_r \\ (y_1 = ry_2 + a_2)_{10} & \rightarrow (10^1 \cdot a_2)_r \\ (y_2 = ry_3 + a_3)_{10} & \rightarrow (10^2 \cdot a_3)_r \\ (y_3 = ry_4 + a_4)_{10} & \rightarrow (10^3 \cdot a_4)_r \\ & \vdots \\ (y_n = 0 + a_n)_{10} & \rightarrow (10^m \cdot a_n)_r \end{align*} \[ \therefore (10^m \cdot a_n + \dots + 100a_3 + 10a_2 + a_1)_r \]

小数部については次のように計算することができる。ここで\( a.b \)のaは小数の整数部、bは小数部を表す。

\begin{align*} (0.x \times r = a_1.b_1)_{10} & \rightarrow \left(\dfrac{1}{10} \times a_1 \right)_r \\ (b_1 \times r = a_2.b_2)_{10} & \rightarrow \left(\dfrac{1}{100} \times a_2 \right)_r \\ (b_2 \times r = a_3.b_3)_{10} & \rightarrow \left(\dfrac{1}{1000} \times a_3 \right)_r \\ & \vdots & \\ (b_n \times r = a_n.0)_{10} & \rightarrow \left(\dfrac{1}{10^m} \times a_n \right)_r \end{align*} \[ \therefore \left(\dfrac{1}{10} \times a_1 + \dfrac{1}{100} \times a_2 + \dfrac{1}{1000} \times a_3 + \dots + \dfrac{1}{10^m} \times a_n \right)_r \]

スクリプティング言語の関数やメソッドを利用した基数変換

Python 3では、2進数・8進数・16進数から10進数へ基数変換するためにint()関数を利用することができる。int()関数の第1引数に、変換したい数値を一重引用符か二重引用符で挟んで指定し、第2引数にその基数の値を指定する。

$ python3
>>> int("1111",2)
15
>>> int("16",8)
14
>>> int("1E",16)
30
>>> exit

変換前の数値にプレフィックス(接頭辞)が付けられていても大丈夫。

>>> int("0b10101",2)
21
>>> int("0o37",8)
31
>>> int("0x9",16)
9
>>> exit

10進数から2進数へ、10進数から8進数へ、10進数から16進数へ基数変換したいときにはそれぞれに専用の関数が用意されている。2進数へ変換する場合にはbin()関数、8進数へ変換する場合にはoct()関数、16進数へ変換する場合にはhex()関数を利用する。

>>> bin(125)
'0b1111101'
>>> bin(125)[2:]
'1111101'
>>> oct(56)
'0o70'
>>> oct(56)[2:]
'70'
>>> hex(64)
'0x40'
>>> hex(64)[2:]
'40'
>>> exit

これらの関数の出力値にはプレフィックス(接頭辞)が付いてくるが、[2:]によってそれを除去することができる。

Python 3では、format()関数やstr.format()メソッドにも10進数を2進数ないしは8進数ないしは16進数に基数変換する能力がある。format()関数とstr.format()メソッドでは次の書式指定子を利用する。

  • 2進数はb、
  • 8進数はo、
  • 16進数の小文字はx、16進数の大文字はX。

次の例では10進数の30を2進数・8進数・16進数にそれぞれ基数変換している。

$ python3
Python 3.13.5
>>> format(30,'b')
'11110'
>>> "{:b}".format(30)
'11110'
>>> format(30,'o')
'36'
>>> "{:o}".format(30)
'36'
>>> format(30,'x')
'1e'
>>> "{:x}".format(30)
'1e'
>>> format(30,'X')
'1E'
>>> "{:X}".format(30)
'1E'
>>> exit

Python 3ではそのうえさらにf-stringsという文字列リテラルを利用する方法がある。次の例では10進数の31を2進数・8進数・16進数にそれぞれ基数変換している。

$ python3
Python 3.13.5
>>> f"{31:b}"
'11111'
>>> f"{31:o}"
'37'
>>> f"{31:x}"
'1f'
>>> f"{31:X}"
'1F'
>>> exit

R言語では2進数・8進数・16進数から10進数への基数変換にstrtoi()関数を利用できる。第1引数には引用符付きで数字を指定し、第2引数にはbase=の後にその数字の基数を指定する。2進数ならば2が基数、8進数ならば8が基数、16進数ならば16が基数。

$ R
R version 4.5.0
> strtoi("11111",base=2)
[1] 31
> strtoi("37",base=8)
[1] 31
> strtoi("1F",base=16)
[1] 31
> q()
Save workspace image? [y/n/c]: n

R言語で10進数から2進数へ基数変換するにはintToBits()関数を利用できる。ただしこの関数はスペースで区切られた2桁の2進法表現をraw型で返す。しかも桁は逆順に並んでいる。そのため、この関数によって返されたデータを整形する処理も一緒に必要になる。

次に10進数の35を2進数に基数変換する処理の例を示す。

$ R
R version 4.5.0
> bin1 = intToBits(35L)
> bin1
 [1] 01 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[26] 00 00 00 00 00 00 00
> typeof(bin1)
[1] "raw"
> bin2 = as.integer(bin1)
> bin2
 [1] 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> bin3 = rev(bin2)
> bin3
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1
> bin4 = paste(bin3,collapse="")
> bin4
[1] "00000000000000000000000000100011"
> bin5 = sub("^0+","",bin4)
> bin5
[1] "100011"
> q()
Save workspace image? [y/n/c]: n

数値リテラルの35Lは35がInteger型の数値であることを表している。それをintToBits()関数に入力して出力された値を変数bin1に代入。しかし出力された値をtypeof()関数で調べてみるとraw型になってしまっている。as.integer()関数によってそれを再びInteger型に戻して変数bin2に代入。次にrev()関数で桁順を反転させて変数bin3に代入。次にpaste()関数によって数字間の空白を取り除いて変数bin4に代入。次にsub()関数によって余分な0を取り除いて最終的な結果を変数bin5に代入している。ただしrev()関数はpaste()関数より前で使う必要があることに要注意。

ちなみに、R言語の代入演算子は<-のはずだと思われたかもしれが、左辺への代入ならば=が使える。

R言語で10進数から16進数へ基数変換するにはas.hexmode()関数が便利。

$ R
R version 4.5.0
> as.hexmode(35L)
[1] "23"
> q()
Save workspace image? [y/n/c]: n

R言語で10進数を8進数へと基数変換する便利な方法はどうもないらしい。上述したアルゴリズムをコード化してちょっとしたスクリプトを組むしかないと思う。

GNU Octaveではbase2dec()関数とdec2base()関数を利用できる。base2dec()関数はr進数から10進数への基数変換をしてくれ、dec2base()関数は10進数からr進数への基数変換をしてくれる。

base2dec()関数では第1引数に変換したい数値を引用符で挟んで指定し、第2引数には第1引数で指定した数値の基数(何進数か)を指定する。dec2base()関数では第1引数に変換したい10進数の数値を指定し、第2引数に変換後の数値の基数(何進数へ変換したいか)を指定する。引数の指定方法が異なることに要注意。

$ octave
GNU Octave, version 9.4.0
octave:1> base2dec("11011",2)
ans = 27
octave:2> dec2base(27,2)
ans = 11011
octave:3> base2dec("33",8)
ans = 27
octave:4> dec2base(27,8)
ans = 33
octave:5> base2dec("1b",16)
ans = 27
octave:6> dec2base(27,16)
ans = 1B
octave:7> exit

Juliaではstring()関数とparse()関数を利用できる。string()関数は10進数からr進数へ基数変換してくれ、parse()関数はr進数から10進数へ基数変換してくれる。

string()関数の第1引数には10進数を指定して第2引数にはbase=で変換先の基数を指定する。parse()関数の第1引数にはデータ型名を指定し、第2引数に文字列リテラルとして変換前の数値を指定し、第3引数では第2引数で指定した数値の基数を指定する。

$ julia
Version 1.11.6
julia> string(8,base=2)
"1000"

julia> parse(Int,"1000",base=2)
8

julia> string(12,base=8)
"14"

julia> parse(Int,"14",base=8)
12

julia> string(13,base=16)
"d"

julia> parse(Int,"d",base=16)
13

julia> exit()

Rubyでは基数変換のために整数オブジェクトの.to_s()メソッドと文字列オブジェクトの.to_i()メソッドを利用することができる。.to_s()メソッドは10進数をr進数へ基数変換するために利用でき、.to_i()メソッドはr進数を10進数に基数変換するために利用できる。

整数オブジェクトの.to_s()メソッドでは()に変換先の基数を指定するが、文字列オブジェクトの.to_i()メソッドでは()に変換元の基数を指定するという違いがある。

ここではRubyのREPL(レプル)であるIRBを利用した。

$ ruby -v
ruby 3.3.8
$ irb -v
irb 1.13.1
$ irb
irb(main):001> 52.to_s(2)
=> "110100"
irb(main):002> "110100".to_i(2)
=> 52
irb(main):003> 37.to_s(8)
=> "45"
irb(main):004> "45".to_i(8)
=> 37
irb(main):005> 29.to_s(16)
=> "1d"
irb(main):006> "1D".to_i(16)
=> 29
irb(main):007> exit

Javaで基数変換をするにはIntegerクラスやLongクラスの.toString()メソッドと.parseInt()メソッドを利用することができる。.toString()メソッドは10進数からr進数への基数変換に利用でき、.parseInt()メソッドはr進数から10進数への基数変換に利用できる。

.toString()メソッドでは第1引数にint型の10進数を指定し、第2引数に変換先の基数を指定する。.parseInt()メソッドでは第1引数にn進数をstring型で指定し、第2引数にその基数を指定する。

JavaにはJShellというREPL(レプル)があるのでここではそれを利用した。

$ jshell
|  JShellへようこそ -- バージョン21.0.8
|  概要については、次を入力してください: /help intro

jshell> Integer.toString(25,2);
$1 ==> "11001"

jshell> Integer.parseInt("11001",2);
$2 ==> 25

jshell> Integer.toString(25,8);
$3 ==> "31"

jshell> Integer.parseInt("31",8);
$4 ==> 25

jshell> Integer.toString(28,16);
$5 ==> "1c"

jshell> Integer.parseInt("1c",16);
$6 ==> 28

jshell> /exit
|  終了します

ScalaでもJavaとまったく同じやり方でIntegerクラスやLongクラスの.toString()メソッドとparseInt()メソッドを使って基数変換を行うことができる。

$ scala
Welcome to Scala 2.11.12 (OpenJDK 64-Bit Server VM, Java 21.0.8).
Type in expressions for evaluation. Or try :help.

scala> Integer.toString(31,2)
res0: String = 11111

scala> Integer.parseInt("11111",2)
res1: Int = 31

scala> Integer.toString(31,8)
res2: String = 37

scala> Integer.parseInt("37",8)
res3: Int = 31

scala> Integer.toString(31,16)
res4: String = 1f

scala> Integer.parseInt("1f",16)
res5: Int = 31

scala> sys.exit

また、BigIntクラスを利用して大きい数値を扱うこともできる。

scala> var bigHex = BigInt("ffffff",16)
bigHex: scala.math.BigInt = 16777215

scala> bigHex.toString(2)
res9: String = 111111111111111111111111

scala> bigHex.toString(8)
res10: String = 77777777

scala> bigHex.toString(10)
res11: String = 16777215

scala> sys.exit

残念ながらここで挙げたいくつかのスクリプティング言語の関数やメソッドはすべて整数部の基数変換にしか対応していない。小数部はアルゴリズムが異なるため、それ向けのスクリプトを書く必要がある。

まとめ

r進数

10進数(decimal numbers)
10を基底とする位取り記数法。0, 1, 2, 3, 4, 5, 6, ..., 9, 10, 11 , 12, ...19, 20, 21, ..., 99, 100, 101, ...のように位を上げてゆく数え方。
2進数(binary numbers)
2を基底とする位取り記数法。0と1の数字だけを用いて、0, 1, 10, 11, 100, 101, 110, 111, 1000, ...のように位を上げてゆく数え方。
16進数(hexadecimal numbers)
16を基底とする位取り記数法。0〜9の次はA, B, C, D, E, F 10, 11, 12, ..., 19, 1A, 1B,..., 1F, 20, 21, ...のように位を上げてゆく数え方。
位取り記数法
数にくらいという概念を導入し、1つ下の位で数字がひと通り数えられるごとに1つ上の位に1つずつ繰り上がってゆく数え方およびその記数法。位はけたとも呼ぶ。
桁値(重み)
位取り記数法において各桁(各位)はそれぞれ異なる数の単位を表している。その単位は桁値または重みと呼ばれている。それぞれの桁の数字はその桁値だけ倍にした数であることを意味している。例えば10進法では、10の位は10倍を意味し、100の位は100倍を意味している。2進法では、10(イチゼロ)の位は10進法での2倍に相当し、100(イチゼロゼロ)の位は10進法での4倍に相当している。

r進数から10進数への基数変換のアルゴリズム

  1. 与えられた数値を整数部と小数部とに分ける。

    16進数を10進数へ基数変換する例を挙げてみた。

    \[ (E941.0F5)_{16} = (E941)_{16} + (0.0F5)_{16} \]
  2. 整数部の各桁を10進数における「各桁の値×桁値」に基数変換し、それらすべての桁を表す項を足し合わせた総和の式にする。

    \[ (E941)_{16} \rightarrow (14 \times 16^3 + 9 \times 16^2 + 4 \times 16^1 + 1 \times 16^0)_{10} \]

    Eは10進数では14に当たる。整数部では1の位の桁値の指数が0から始まることに要注意。

  3. 小数部の各桁を10進数における「各桁の値×桁値」に基数変換し、それらすべての桁を表す項を足し合わせた総和の式にする。

    \[ (0.0F5)_{16} \rightarrow (0 \times \dfrac{1}{16} + 15 \times \dfrac{1}{16^2} + 5 \times \dfrac{1}{16^3})_{10} \]

    Fは10進数では15に当たる。

  4. 整数部を計算する。

    \begin{align*} & (14 \times 16^3 + 9 \times 16^2 + 4 \times 16^1 + 1 \times 16^0)_{10} \\ & = (14 \times 4096 + 9 \times 256 + 4 \times 16 + 1 \times 1)_{10} \\ & = (57344 + 2304 + 64 + 1)_{10} \\ & = (59713)_{10} \end{align*}
  5. 小数部を計算する。

    \begin{align*} & (0 \times \dfrac{1}{16} + 15 \times \dfrac{1}{16^2} + 5 \times \dfrac{1}{16^3})_{10} \\ & = (0 \times 0.0625 + 15 \times 0.00390625 + 5 \times 0.000244140625)_{10} \\ & = (0 + 0.05859375 + 0.001220703125)_{10} \\ & = (0.059814453125)_{10} \end{align*}
  6. 整数部の計算結果と小数部の計算結果を足し合わせる。

    \[ (59713 + 0.059814453125)_{10} = (59713.059814453125)_{10} \]

10進数・2進数・8進数・16進数の桁値(各々の位の重み)

10進数とその桁値
10進数の桁 桁値
0.0000000001 \( \dfrac{1}{10^{10}} \)
0.000000001 \( \dfrac{1}{10^9} \)
0.00000001 \( \dfrac{1}{10^8} \)
0.0000001 \( \dfrac{1}{10^7} \)
0.000001 \( \dfrac{1}{10^6} \)
0.00001 \( \dfrac{1}{10^5} \)
0.0001 \( \dfrac{1}{10^4} \)
0.001 \( \dfrac{1}{10^3} \)
0.01 \( \dfrac{1}{10^2} \)
0.1 \( \dfrac{1}{10^1} \)
1 \( 10^0 \)
10 \( 10^1 \)
100 \( 10^2 \)
1000 \( 10^3 \)
10000 \( 10^4 \)
100000 \( 10^5 \)
1000000 \( 10^6 \)
10000000 \( 10^7 \)
100000000 \( 10^8 \)
1000000000 \( 10^9 \)
10000000000 \( 10^{10} \)

2進数とその桁値(10進数表記)
2進数の桁 対応する10進数 桁値
0.00000000001 0.0009765625 \( \dfrac{1}{2^{10}} \)
0.0000000001 0.001953125 \( \dfrac{1}{2^9} \)
0.000000001 0.00390625 \( \dfrac{1}{2^8} \)
0.00000001 0.0078125 \( \dfrac{1}{2^7} \)
0.0000001 0.015625 \( \dfrac{1}{2^6} \)
0.000001 0.03125 \( \dfrac{1}{2^5} \)
0.00001 0.0625 \( \dfrac{1}{2^4} \)
0.0001 0.125 \( \dfrac{1}{2^3} \)
0.01 0.25 \( \dfrac{1}{2^2} \)
0.1 0.5 \( \dfrac{1}{2^1} \)
1 1 \( 2^0 \)
10 2 \( 2^1 \)
100 4 \( 2^2 \)
1000 8 \( 2^3 \)
10000 16 \( 2^4 \)
100000 32 \( 2^5 \)
1000000 64 \( 2^6 \)
10000000 128 \( 2^7 \)
100000000 256 \( 2^8 \)
1000000000 512 \( 2^9 \)
10000000000 1024 \( 2^{10} \)

8進数とその桁値(10進数表記)
8進数の桁 対応する10進数 桁値
0.0000000001 0.0000000009313226 \( \dfrac{1}{8^{10}} \)
0.000000001 0.000000007450581 \( \dfrac{1}{8^9} \)
0.00000001 0.00000005960464 \( \dfrac{1}{8^8} \)
0.0000001 0.0000004768372 \( \dfrac{1}{8^7} \)
0.000001 0.000003814697 \( \dfrac{1}{8^6} \)
0.00001 0.00003051758 \( \dfrac{1}{8^5} \)
0.0001 0.0002441406 \( \dfrac{1}{8^4} \)
0.001 0.001953125 \( \dfrac{1}{8^3} \)
0.01 0.015625 \( \dfrac{1}{8^2} \)
0.1 0.125 \( \dfrac{1}{8^1} \)
1 1 \( 8^0 \)
10 8 \( 8^1 \)
100 64 \( 8^2 \)
1000 512 \( 8^3 \)
10000 4096 \( 8^4 \)
100000 32768 \( 8^5 \)
1000000 262144 \( 8^6 \)
10000000 2097152 \( 8^7 \)
100000000 16777216 \( 8^8 \)
1000000000 134217728 \( 8^9 \)
10000000000 1073741824 \( 8^{10} \)

16進数とその桁値(10進数表記)
16進数の桁 対応する10進数 桁値
0.0000000001 0.0000000000009094947 \( \dfrac{1}{16^{10}} \)
0.000000001 0.00000000001455192 \( \dfrac{1}{16^9} \)
0.00000001 0.0000000002328306 \( \dfrac{1}{16^8} \)
0.0000001 0.00000000372529 \( \dfrac{1}{16^7} \)
0.000001 0.00000005960464 \( \dfrac{1}{16^6} \)
0.00001 0.0000009536743 \( \dfrac{1}{16^5} \)
0.0001 0.00001525879 \( \dfrac{1}{16^4} \)
0.001 0.0002441406 \( \dfrac{1}{16^3} \)
0.01 0.00390625 \( \dfrac{1}{16^2} \)
0.1 0.0625 \( \dfrac{1}{16^1} \)
1 1 \( 16^0 \)
10 16 \( 16^1 \)
100 256 \( 16^2 \)
1000 4096 \( 16^3 \)
10000 65536 \( 16^4 \)
100000 1048576 \( 16^5 \)
1000000 16777216 \( 16^6 \)
10000000 268435456 \( 16^7 \)
100000000 4294967296 \( 16^8 \)
1000000000 68719476736 \( 16^9 \)
100000000000 1099511627776 \( 16^{10} \)

10進数からr進数への基数変換のアルゴリズム

  1. 与えられた数値を整数部と小数部とに分かる。

    ここでは10進数の59713.059814453125を16進数へ基数変換する例を挙げる。

    \[ (59713.059814453125)_{10} = (59713)_{10} + (0.059814453125)_{10} \]
  2. 整数部に連続除法(剰余法)を適用する。

    ここで連続除法(剰余法)とは次のことを指す。各桁の値を変換したい基数で割り算し、その余りを記録し、そして割り算の答えの整数部を更に基数で割り算し、その余りを記録し、これを答えがゼロに達するまで繰り返す。答えが循環小数になる場合は適当なところで計算を打ち切る。

    \[ \begin{array}{r|l:l} \text{割る数} & \text{割られる数} & \text{余り} \\ \hline 16 & 59713 \\ \hline 16 & 3732 & 1 \\ \hline 16 & 233 & 4 \\ \hline 16 & 14 & 9 \\ \hline & 0 & 14 \rightarrow E \end{array} \] \[ \therefore E941 \]
  3. 小数部に乗算法を適用する。

    ここで乗算法とは次のことを指す。各桁の値(小数)を変換したい基数で掛け算し、その答えから整数部を差し引いた値を更に基数で掛け算し、小数部がゼロになるまでこの計算を繰り返す。その際、各桁の乗算ごとに得られた整数部の値を記録する。掛けても掛けても小数部が無くならない場合は適当なところで計算を打ち切る。

    \[ \begin{array}{r|l:l} \text{掛ける数} & \text{掛けられる数} & \text{差し引いた整数部}\\ \hline 16 & 0.059814453125 \\ \hline 16 & 0.95703125 & 0 \\ \hline 16 & 0.3125 & 15 \rightarrow F \\ \hline 16 & 0 & 5 \end{array} \] \[ \therefore 0.0F5 \]

    \( 16 \times 0.95703125 = 15.3125 \)になるが、そこから整数部である15を差し引いて\( 15.3125 - 15 = 0.3125 \)、小数部の0.3125だけを次の「掛けられる数」にする点に要注意。

  4. 得られた数値の整数部と小数部を足し合わせる。

    \[ (E941)_{16} + (0.0F5)_{16} = (E941.0F5)_{16} \]

コメント

このブログの人気の投稿

LATEXで数式:指数と順列などで使う添数・添字

LibreOffice 6 Calcでフォーム(ダイアログ)を作成してマクロで表示

LibreOffice Calc 4.3で数値を3桁ずつカンマで区切る