Shironetsu Blog

@shironetsuのブログ

十六進表記が十進法でも読めると嬉しい



十六進法で表記されたハッシュ値を扱っていると、たまに十進法でも有効な文字列になっていることがある。
つまり、十六進表記だがどの桁も0から9のいずれかで、aからfを含まないということ。実例として、


{
\begin{align}
(123456)_{16} = (1193046)_{10}
\end{align}
}

など。反対に、


{
\begin{align}
(\rm{bc614e})_{16} = (12345678)_{10}
\end{align}
}

{1, 5, 6} 桁目に それぞれ {\rm{e, c, b}} を含むため十進法で読めない。

このような性質を満たす数のことを 偽十進法整数 と呼ぶことにする。すなわち、{n} が偽十進法整数であるとは、{0} 以上 {9} 以下の整数の列


{
\begin{align}
a_0, a_1, a_2,\cdots, a_{m}
\end{align}
}

が存在して、


{
\begin{align}
n = a_0 + a_1 \cdot 16 + a_2 \cdot 16^2 + \cdots a_{m} \cdot 16^m
\end{align}
}

を満たすということ。

7桁程度の偽十六進整数ならさして珍しくないことは、{(16)^7}の数のうち、割合として


{
\begin{align}
\left(\frac{10}{16}\right)^6 = 0.037\cdots
\end{align}
}

がこの性質を満たすことから分かる。gitのログで表示されるコミットハッシュの短縮形のデフォルト桁数がこの7桁*1なので、目にする機会も多い。

さて、偽十進法整数は具体的にどれくらい存在するだろうか。非負整数 {n} 以下の非負の偽十進法整数の個数を {p_n} で表すことにする。なお、特に進数表記をしていない限り以下では十進法。


{
\begin{align}
\begin{array}{|r|r|}
\hline
n & p_n \\ \hline\hline
0 & 1 \\ \hline
1 & 2 \\ \hline
2 & 3 \\ \hline
\vdots & \vdots \\ \hline
10 & 10 \\ \hline
100 & 65 \\ \hline
1000 & 400 \\ \hline
10000 & 2711 \\ \hline
100000 & 18700 \\ \hline
1000000 & 100000 \\ \hline
10000000 & 989681 \\ \hline
100000000 & 6000000 \\ \hline
\end{array}
\end{align}
}

{p_{n}/n}{n\rightarrow \infty}{0} に漸近することはほぼ明らか。では、{n} 以下の偽十進法非負整数とそうでない数が同数になるのはいつだろうか。すなわち、


{
\begin{align}
n+1-p_{n} = p_{n}
\end{align}
}

となるのはいつか。計算すると、{n=199} ただひとつがこの性質を満たすことが分かる。

少し一般化して、


{
\begin{align}
n+1 = k\,p_n
\end{align}
}

を満たすような整数 {k} が存在する {n} を探そう。 {k=2} が上で調べた場合にあたる。{10^9} 以下での結果が下表。


{
\begin{align}
\begin{array}{|r|r|r|}
\hline
n & p_n & k \\\hline\hline
0 & 1 & 1 \\ \hline
1 & 2 & 1 \\ \hline
2 & 3 & 1 \\ \hline
3 & 4 & 1 \\ \hline
4 & 5 & 1 \\ \hline
5 & 6 & 1 \\ \hline
6 & 7 & 1 \\ \hline
7 & 8 & 1 \\ \hline
8 & 9 & 1 \\ \hline
9 & 10 & 1 \\ \hline
199 & 100 & 2 \\ \hline
2999 & 1000 & 3 \\ \hline
3999 & 1000 & 4 \\ \hline
4151 & 1038 & 4 \\ \hline
4159 & 1040 & 4 \\ \hline
7999 & 2000 & 4 \\ \hline
8311 & 2078 & 4 \\ \hline
8319 & 2080 & 4 \\ \hline
8399 & 2100 & 4 \\ \hline
8471 & 2118 & 4 \\ \hline
8479 & 2120 & 4 \\ \hline
11999 & 3000 & 4 \\ \hline
12631 & 3158 & 4 \\ \hline
12639 & 3160 & 4 \\ \hline
12799 & 3200 & 4 \\ \hline
15999 & 4000 & 4 \\ \hline
16791 & 4198 & 4 \\ \hline
16799 & 4200 & 4 \\ \hline
16951 & 4238 & 4 \\ \hline
16959 & 4240 & 4 \\ \hline
19999 & 5000 & 4 \\ \hline
21111 & 5278 & 4 \\ \hline
21119 & 5280 & 4 \\ \hline
21199 & 5300 & 4 \\ \hline
21271 & 5318 & 4 \\ \hline
21279 & 5320 & 4 \\ \hline
23999 & 6000 & 4 \\ \hline
25431 & 6358 & 4 \\ \hline
25439 & 6360 & 4 \\ \hline
25599 & 6400 & 4 \\ \hline
27999 & 7000 & 4 \\ \hline
29591 & 7398 & 4 \\ \hline
29599 & 7400 & 4 \\ \hline
29751 & 7438 & 4 \\ \hline
29759 & 7440 & 4 \\ \hline
31999 & 8000 & 4 \\ \hline
33911 & 8478 & 4 \\ \hline
33919 & 8480 & 4 \\ \hline
33999 & 8500 & 4 \\ \hline
34071 & 8518 & 4 \\ \hline
34079 & 8520 & 4 \\ \hline
35999 & 9000 & 4 \\ \hline
38231 & 9558 & 4 \\ \hline
38239 & 9560 & 4 \\ \hline
38399 & 9600 & 4 \\ \hline
39999 & 10000 & 4 \\ \hline
49999 & 10000 & 5 \\ \hline
59999 & 10000 & 6 \\ \hline
74879 & 12480 & 6 \\ \hline
74999 & 12500 & 6 \\ \hline
119999 & 20000 & 6 \\ \hline
149999 & 25000 & 6 \\ \hline
152639 & 25440 & 6 \\ \hline
179999 & 30000 & 6 \\ \hline
227999 & 38000 & 6 \\ \hline
230399 & 38400 & 6 \\ \hline
239999 & 40000 & 6 \\ \hline
699999 & 100000 & 7 \\ \hline
799999 & 100000 & 8 \\ \hline
899999 & 100000 & 9 \\ \hline
999999 & 100000 & 10 \\ \hline
1079999 & 108000 & 10 \\ \hline
1099999 & 110000 & 10 \\ \hline
1122999 & 112300 & 10 \\ \hline
1123079 & 112308 & 10 \\ \hline
1397339 & 155260 & 9 \\ \hline
1439999 & 160000 & 9 \\ \hline
1799999 & 200000 & 9 \\ \hline
1999999 & 200000 & 10 \\ \hline
2999999 & 300000 & 10 \\ \hline
3369999 & 337000 & 10 \\ \hline
3399999 & 340000 & 10 \\ \hline
3999999 & 400000 & 10 \\ \hline
4494399 & 449440 & 10 \\ \hline
4499999 & 450000 & 10 \\ \hline
4999999 & 500000 & 10 \\ \hline
5658739 & 565874 & 10 \\ \hline
5659999 & 566000 & 10 \\ \hline
5660799 & 566080 & 10 \\ \hline
5699999 & 570000 & 10 \\ \hline
5999999 & 600000 & 10 \\ \hline
6783879 & 678388 & 10 \\ \hline
6783999 & 678400 & 10 \\ \hline
6799999 & 680000 & 10 \\ \hline
6999999 & 700000 & 10 \\ \hline
7948339 & 794834 & 10 \\ \hline
7949999 & 795000 & 10 \\ \hline
7950399 & 795040 & 10 \\ \hline
7999999 & 800000 & 10 \\ \hline
10999999 & 1000000 & 11 \\ \hline
11999999 & 1000000 & 12 \\ \hline
12999999 & 1000000 & 13 \\ \hline
13999999 & 1000000 & 14 \\ \hline
14999999 & 1000000 & 15 \\ \hline
15999999 & 1000000 & 16 \\ \hline
17279999 & 1080000 & 16 \\ \hline
17599999 & 1100000 & 16 \\ \hline
17967999 & 1123000 & 16 \\ \hline
17969279 & 1123080 & 16 \\ \hline
20215499 & 1347700 & 15 \\ \hline
20249999 & 1350000 & 15 \\ \hline
23799999 & 1700000 & 14 \\ \hline
24359999 & 1740000 & 14 \\ \hline
27999999 & 2000000 & 14 \\ \hline
29999999 & 2000000 & 15 \\ \hline
31999999 & 2000000 & 16 \\ \hline
40466249 & 2697750 & 15 \\ \hline
40499999 & 2700000 & 15 \\ \hline
44999999 & 3000000 & 15 \\ \hline
47999999 & 3000000 & 16 \\ \hline
53919999 & 3370000 & 16 \\ \hline
54399999 & 3400000 & 16 \\ \hline
63999999 & 4000000 & 16 \\ \hline
71910399 & 4494400 & 16 \\ \hline
71999999 & 4500000 & 16 \\ \hline
79999999 & 5000000 & 16 \\ \hline
90539839 & 5658740 & 16 \\ \hline
90559999 & 5660000 & 16 \\ \hline
90572799 & 5660800 & 16 \\ \hline
91199999 & 5700000 & 16 \\ \hline
95999999 & 6000000 & 16 \\ \hline
108542079 & 6783880 & 16 \\ \hline
108543999 & 6784000 & 16 \\ \hline
108799999 & 6800000 & 16 \\ \hline
111999999 & 7000000 & 16 \\ \hline
127173439 & 7948340 & 16 \\ \hline
127199999 & 7950000 & 16 \\ \hline
127206399 & 7950400 & 16 \\ \hline
127999999 & 8000000 & 16 \\ \hline
169999999 & 10000000 & 17 \\ \hline
179999999 & 10000000 & 18 \\ \hline
189999999 & 10000000 & 19 \\ \hline
199999999 & 10000000 & 20 \\ \hline
209999999 & 10000000 & 21 \\ \hline
219999999 & 10000000 & 22 \\ \hline
229999999 & 10000000 & 23 \\ \hline
239999999 & 10000000 & 24 \\ \hline
249999999 & 10000000 & 25 \\ \hline
259999999 & 10000000 & 26 \\ \hline
292499999 & 11700000 & 25 \\ \hline
292562049 & 11702482 & 25 \\ \hline
299999999 & 12000000 & 25 \\ \hline
303202499 & 12128100 & 25 \\ \hline
323447999 & 13477000 & 24 \\ \hline
323999999 & 13500000 & 24 \\ \hline
367999999 & 16000000 & 23 \\ \hline
395929599 & 17996800 & 22 \\ \hline
395999999 & 18000000 & 22 \\ \hline
417999999 & 19000000 & 22 \\ \hline
420199999 & 19100000 & 22 \\ \hline
439999999 & 20000000 & 22 \\ \hline
459999999 & 20000000 & 23 \\ \hline
479999999 & 20000000 & 24 \\ \hline
499999999 & 20000000 & 25 \\ \hline
519999999 & 20000000 & 26 \\ \hline
599999999 & 24000000 & 25 \\ \hline
606434149 & 24257366 & 25 \\ \hline
647459999 & 26977500 & 24 \\ \hline
647999999 & 27000000 & 24 \\ \hline
719999999 & 30000000 & 24 \\ \hline
749999999 & 30000000 & 25 \\ \hline
779999999 & 30000000 & 26 \\ \hline
898999999 & 35960000 & 25 \\ \hline
899027074 & 35961083 & 25 \\ \hline
899999999 & 36000000 & 25 \\ \hline
909999999 & 36400000 & 25 \\ \hline
999999999 & 40000000 & 25 \\ \hline
\end{array}
\end{align}
}

github.com

{n} は十進で下位に9が並ぶ傾向があるが、完全ではない。実際、

  • {n=4151, 8311, 8471} 等で一の位が {1}
  • {n=899027074} で一の位が {4}

となっていることが観察できる。

この「傾向」はどう説明付けられるだろうか。{p_n} の振る舞いを見よう。


{
\begin{align}
\begin{array}{|r|r|r|} \hline
n\,(\rm{dec}) & n\,(\rm{hex}) & p_{n}\,(\rm{dec}) \\ \hline \hline
(3)_{10} & (\rm{3})_{16} & (4)_{10}\\\hline
(31)_{10} & (\rm{1f})_{16} & (20)_{10}\\\hline
(314)_{10} & (\rm{13a})_{16} & (140)_{10}\\\hline
(3141)_{10} & (\rm{c45})_{16} & (1000)_{10}\\\hline
(31415)_{10} & (\rm{7ab7})_{16} & (8000)_{10}\\\hline
(314159)_{10} & (\rm{4cb2f})_{16} & (50000)_{10}\\\hline
(3141592)_{10} & (\rm{2fefd8})_{16} & (300000)_{10}\\\hline
(31415926)_{10} & (\rm{1df5e76})_{16} & (2000000)_{10}\\\hline
(314159265)_{10} & (\rm{12b9b0a1})_{16} & (13000000)_{10}\\\hline
\end{array}
\end{align}
}

じっと見ると、{p_n} を簡単に計算する方法が分かる。

たとえば、


{
\begin{align}
(314159265)_{10} = (\rm{12b9b0a1})_{16}
\end{align}
}

以下の偽十進非負整数は、


{
\begin{align}
(12999999)_{16} < (\rm{12b9b0a1})_{16} < (1300000)_{16} 
\end{align}
}

の関係が成り立つから、


{
\begin{align}
(0)_{16}, (1)_{16}, \cdots , (12999999)_{16}
\end{align}
}

{(1300000)_{10}} 個である。

言葉で説明しよう。{n} を 十六進表記で上の位から見て、最初に見つかる {9}より大きい文字(aからf)とそれ以下の桁の文字を全て {9} で置き換えると、それが {n} を超えない最大の偽十進法整数である(十六進法で読む)。その文字列を十進法で読み替えて1を加えれば {p_n} を得る。


{
\begin{align}
(3141592653589793238462643)_{10} &= (\rm{299421439a0abd72cb0b3})_{16} \\
p_n &= (299421439999999999999)_{10} + (1)_{10}\\
&= (299421440000000000000)_{10}
\end{align}
}

という具合に。

{n+1 = k\,p_n} を満たす {n} の下位の桁に9が並びがちな傾向はこのことから理解できる。そもそも {p_n}{10} の大きな冪を約数に持ちやすく、そのため {n=k\,p_n-1} は下位の桁に多くの9が並ぶ。非常に粗いヒューリスティックな議論ではあるが。

さて、未解決の問題がある。{n+1=k\,p_n} を満たす {n} が、10で割って {1,4,9} 以外の剰余を持つことはあるだろうか?(たぶん存在すると思う)

*1:`--abbrev` オプションで変更できる。