圆周率里包含你的银行卡密码吗?
这个问题挺有意思,非数学专业,就从计算机的角度分析一下这个问题吧。
-----我是条分割线-----
为了分析这个问题,我先用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])+'\n')
因为我用的是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])+'\n')
-----还是条分割线-----
大家不要私信给我发银行卡密码了!很危险的!真要查的话,可以看评论置顶,有个朋友分享了在线查询的链接。范围精确到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])+'\n')
需要的文件在这里~
六位银行卡密码出现位置
文件:Pi-stat.txt
密码:8rc9
生日出现位置
密码:v4o4
10亿位圆周率
密码:drq8
2500万位圆周率
密码:0aq8
------------2018.08.06--------
从今天起禁止任何形式的转载。