这个问题挺有意思,非数学专业,就从计算机的角度分析一下这个问题吧。
-----我是条分割线-----
为了分析这个问题,我先用y-cruncher跑出了π的前10亿位,感觉应该够用!
不够用也没办法了,内存有限,而且跑程序时CPU占用率100%,风扇吹的我心慌。
计算前10亿位共用时190.515秒,数据以txt的格式保存,大小976.563MB。
下面开始我们的分析工作。
先简单的搜索一下,发现自己能想到的几个六位数字都出现了(包括我的银行卡密码)
举几个例子:
注:每行有1024个字符,所以计算公式应为1024*(行数-1)+列数-2,其中2为开头的“3.”
但是不可能手动把000000~999999全验证一遍吧(虽然我今天很闲),还是要写个程序跑一下。
不考虑复杂度问题的话,代码很快就写完了,只有短短的14行。
pwds = [] for num in range(1000000): pwds.append("0" * (6 - len(str(num))) + str(num)) with open("Pi-1000000000.txt","r")as f: pai=f.read() #输出字符串的长度和π的前109位 print(len(pai),pai[0:110]) stat = [] for pwd in pwds: stat.append([pwd,pai.index(pwd)-1]) if len(stat) % 1000 == 1: print(stat[-1]) with open("Pi-stat.txt","w")as f: for data in stat: f.write(data[0]+':'+str(data[1])+'
')
因为我用的是index,如果密码不存在的话,则会直接抛出异常。但是我的直觉是000000~999999是都存在的(其实是我懒得多写代码了)
检索的速度大概是1000条/秒,接下来就是耐心的等待过程。
程序跑完了!不出所料,所有的六位银行卡密码在π中都是存在的。
最后出现的密码是569540,位于小数点后14,118,307位.(10亿位有点过剩啊!)
同时我也把数据上传到百度网盘了,感兴趣的朋友们可以下载看一下。所有需要的文件都在最下方。需要的朋友自取。
-----又是条分割线-----
第一次收到这么多的赞。
于是我又写了个程序把π前10亿位中的生日给跑了出来,生日的范围为1920~2020共计101年。
上代码~供有兴趣的朋友研究,可以一起讨论如何计算的更快。(感觉这个完全可以出一个面试题的!我水平是不太行,下面是我想到的方法。)
month = {'01':31,'02':28,'03':31, '04':30,'05':31,'06':30, '07':31,'08':31,'09':30, '10':31,'11':30,'12':31} def judge(Jdate): if int(Jdate[0:4]) < 1920 or int(Jdate[0:4]) > 2021: return False else: if int(Jdate[4:6]) > 12 or int(Jdate[4:6]) == 0: return False else: p = month[Jdate[4:6]] if int(Jdate[4:6]) == 2 and int(Jdate[0:4])%4 == 0: p = p+1 if int(Jdate[6:8]) > p or int(Jdate[6:8]) == 0: return False else: return True with open("Pi-1000000000.txt","r")as f: pai=f.read() #输出字符串的长度和π的前109位 print(len(pai),pai[0:110]) stat = [] for num in range(2,len(pai)-8): if judge(pai[num:num+8]): stat.append([pai[num:num+8],num-1]) if num % 1000000 == 0: print(num) stat.sort() with open("Pi-birthday.txt","w")as f: for data in stat: f.write(data[0]+':'+str(data[1])+'
')
-----还是条分割线-----
大家不要私信给我发银行卡密码了!很危险的!真要查的话,可以看评论置顶,有个朋友分享了在线查询的链接。范围精确到2亿位。
下面的内容非程序员可忽略...
经评论区的朋友们启发,而且实在受不了别人喷我程序运行的慢了。又写了一个更快的检索6位数字(就是所谓的银行卡密码)的算法。
感兴趣的程序员可以看一下。我感觉速度还行。十几秒钟就能检索完毕。更快的我暂时也还没想到..毕竟答主还只是一个大二在校生,也没搞过ACM竞赛,水平有限。
#将000000~999999存到字典中,初始化出现的位置为正无穷(用10亿+1代替) dic = {} for num in range(1000000): dic["0" * (6 - len(str(num))) + str(num)] = 1000000001 #读取π with open("Pi-1000000000.txt","r")as f: pai=f.read() #输出字符串π的长度和π的前109位 print(len(pai),pai[0:110]) stat = [] #p=1,跳过了"3." p = 1 #p允许的最大数值 p_max = len(pai)-1000000 ''' 倒序查找,开始时从第1000001位向第1位检索, 检索到第1位时,若字典中仍存在无穷大,则从 2000001位向1000001位检索。以此类推,直到 字典中不存在无穷大或者p大于p_max ''' while 1000000001 in dic.values() and p<p_max: for i in range(p+1000000,p,-1): pwd = pai[i:i+6] if i < dic[pwd]: dic[pwd] = i-1 if i%100000 == 0: print(i) p = p+1000000 with open("pi-stat.txt",'w')as f: for item in dic.items(): f.write(item[0]+':'+str(item[1])+'
')
需要的文件在这里~
六位银行卡密码出现位置
文件:Pi-stat.txt
密码:8rc9
生日出现位置
密码:v4o4
10亿位圆周率
密码:drq8
2500万位圆周率
密码:0aq8
------------2018.08.06--------
从今天起禁止任何形式的转载。
这是经典问题,常常用来区分懂不懂数学的人。
普通人常常会认为:无限不循环的东西,一定包含所有可能性。比如“在无限多个平行宇宙里,总有一个宇宙里你会爱上我”
对不起,数轴上0到1之间有无数个不相同的点,没一个大于2的
在回答这个问题之前,我认为有必要简要介绍一下圆周率 的历史。
众所周知, 是圆周长和直径的比值,是数学上的一个常数(即便宇宙崩塌了, 永远都是 )。就是这样一个永恒的常数引得了从古至今无数数学大佬的苦苦追寻。
首先欢迎祖冲之闪亮登场,他运用刘徽开创的割圆法来寻找 的近似值。
简单地说,曲线的长度我算不出来(牛顿表示呵呵),直线我总能算吧,那我就在圆上取很多点,把它们用直线连起来,这些直线的长度之和就差不多是圆的周长了嘛。
这个方法听起来很普通,它也确实很普通,但是顶不住祖冲之牛逼。
他就凭借这个思路,在 1500 年前的计算条件下,计算出了 的两个近似值。
一个是 ,被称为「约率」, 用于进行近似计算。
另一个是 ,被称为「密率」, 用于准确计算。
至于到底有多准,假设地球是个球体,用这个近似值来计算赤道的周长,误差小于我书桌面前这扇窗的长度。值得指出的是, 这个上限(upper bound)是分母小于 16600 的所有分数中最准的一个。
但可能祖冲之到死也没想到,无论他再怎么努力,也是不可能找出一个准确表示 pi 取值的分数,i.e. 故事来到十八世纪,瑞士数学家 Johann Heinrich Lambert(被 analysis 虐杀过的朋友们应该不会忘记 lambert series 吧,dei,就是这货整出来的)证明了 是一个无理数(irrational number),换句话说就是一个不讲理的数,它无论如何也无法被表示成两个整数的比值。
这一结论一下子就干翻了一大群历史上想要求出 的精确值的数学家。
你们想都别想了,小爷我不仅无限还不循环,你求一个试试?
到了十九世纪,数学家们意识到, 这货就是丫一变态,不仅无理,还超越 (transcendental number)。
至于什么是超越,请大家自行暂时屏蔽一下卡路里这三个字,且听我慢慢道来。
超越的意思就是,这个数无法被表示成代数方程(algebraic equation)的根。
听起来很高端,实际上就是 不可能满足任何一个系数为整数的方程 , 即 。打个比方, 是一个无理数,但不是一个超越数。因为 这个方程的一个正数解就是 。如果一个数无理但是不超越,我们虽然找不到它的精确值到底是多少,但是我们可以找到一个和它相关的方程来分析这个数的性质和特点。
更具体地说,如果直接表白不行,就拉长战线,旁敲侧击。
很可惜,这一理论对 不适用。
如果旁敲侧击也不行,那就远观而不亵玩焉吧。
历史的车轮碾压到现代,数学家们想证明 是否是一个正规数(normal number) 。
什么是 normal,用另一位数学大神 Henri Poincare 的话来说就是:
Mathematics is the art of giving the same name to different things. Poetry is the art of giving different names to the same thing.
数学是一种给不同的事物起同一个名字的艺术;诗歌则是一种给同样的事物起不同名字的艺术。
说得莫名地有道理有木有!
Anyway, normal 在数学上有时是指垂直这样一个概念,但在这里是指随机分布的意思。
比如概率里的正态分布就来源于英文的 normal distribution。
那么什么叫一个随机分布的数?
就是在这样的一个无限不循环的数字里,任何的一数串字(比如,1,16, 5201314 blah~blah~blah)出现的频率都是一样的。
注意!!!是任何一串数字!!! 比如你的银行卡密码 ~
银行卡密码这个概念不好,太俗。
正确的表达方式应该是,如果 被证明了是一个 normal number,那么无论你曾深爱过谁,她的生日,她的身高,她冬天会不会手冷,周末爱不爱睡懒觉,只要能被数字表示出来,你都能在 那无限不循环的「长发」中,找到它的身影。
再或者说,如果你现在拿出一个圆规,画出一个圆,仔细盯着它看一会儿,就会明白 的伟大,因为无论是宇宙的诞生还是地球的毁灭,一切的一切,全部都在你眼前。
然而 是不是一个正规数,时至今日,并没有被证明。
但,我看好你哟!
感谢能看完到这里的人(如果有的话),我知道自己有点能扯。
另外,有知友提到一个猜想: 在二进制下是正规的。
关于这个问题,我有些许心得想和大家分享。
对于无趣的人,我的回答是「这个猜想没有被证明,只是很接近」。
对于有趣的人,我的回答如下: