@交换子 提出的「交错法」确实是构造所求双射的标准思路。
然而因为有理数有两种不同的表示方式,比如 1/2 = 0.5000... = 0.4999...,「交错法」并不能得到一个双射。
这个帖子给出了一种解决这一问题的方法:
我简述如下。首先,把原问题转化为构造 (0,1] 到 (0,1] * (0,1] 的双射。这一步很简单,因为 [0,1] 与 (0,1] 之间有一个平凡的双射:把 0 映射为 1,1 映射为 1/2,1/2 映射为 1/3 …… 其它数不动。
然后再使用交错法。设 (0,1] * (0,1] 中某一点为 (a,b),把 a、b 都表示成十进制小数的形式。例如:
a = 0.1012008005...
b = 0.0045003026...
如果 a 或者 b 是有理数,那么选择 9 循环的那种表示形式,而不是 0 循环的那种。
然后,把两个十进制小数分段,具体分法是在所有非 0 数位后分割:
a = 0.1 01 2 008 005 ...
b = 0.004 5 003 02 6 ...
因为我们从来不选择无限个 0 循环的那种表示形式,这种分割一定可以得到无限段。
最后,把分割出的各段进行交错,得到 (a,b) 在 (0,1] 中的像:
0.1 004 01 5 2 003 008 02 005 6 ...
可以验证,上面的过程反过来同样可以进行,这样构造出来的就是 (0,1] * (0,1] 到 (0,1] 的双射了。