关于网上传言圆周率中隐藏自己银行卡密码问题,今天我们来实际测试下。
这个问题挺有意思,为了分析这个问题,我们先用y-cruncher跑出了π的前10亿位,感觉应该够用!
计算前10亿位共用时190.515秒,数据以txt的格式保存,大小976.563MB。
下面开始我们的分析工作。
先简单的搜索一下,发现自己能想到的几个六位数字都出现了(包括我的银行卡密码)
举几个例子:
000000出现在小数点后第1,699,927位
111111出现在小数点后第255,945位
222222出现在小数点后第963,024位
123456出现在小数点后第2,458,885位
注:每行有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亿位中的生日给跑出来,生日的范围为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]) 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')
下面的内容非程序员可忽略...
又写了一个更快的检索6位数字(银行卡密码)的算法。感兴趣的程序代码爱好者可以看一下。我感觉速度还行。十几秒钟就能检索完毕。
#将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
for i in range(p+1000000,p,-1):
pwd = pai[i:i+6]
if i
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')
领取专属 10元无门槛券
私享最新 技术干货