π-Day快乐:Python可视化π
今天是3.14,正好是圆周率 π \pi π 的前3位,因此数学界将这一天定为 π \bold{\pi} π day。
π \pi π 可能是最著名的无理数了,人类对 π \pi π 的研究从未停止。目前人类借助计算机已经计算到 π \pi π 小数点后31.4万亿位了!这个记录是由来自Google的日本女程序员岩尾遥创造的。据说该计算程序在25台虚拟机上运行了121天,涉及170TB的数据,最终获得精确到 π \pi π 小数点后31.4万亿位的成绩。
计算 π \pi π 的精度也是衡量计算机算力的一种方法,该方法始于冯·诺依曼。直到今天依然有很多数学家在孜孜不倦地研究 π \pi π 的各种性质,甚至有人认为 π \pi π 小数位蕴含着宇宙的终极奥秘。今天我们用Python将 π \pi π 可视化,看看会诞生什么惊人的图案。
文章目录
- 思路
- 点图
- 线段图
- 结论
思路
首先,我从网上下载了 π \pi π 小数点后100万位,保存在文本文件中。每50位一行,数据张这个样子:
14159265358979323846264338327950288419716939937510
58209749445923078164062862089986280348253421170679
82148086513282306647093844609550582231725359408128
48111745028410270193852110555964462294895493038196
44288109756659334461284756482337867831652712019091
45648566923460348610454326648213393607260249141273
72458700660631558817488152092096282925409171536436
然后我会用一定规则来可视化[0-9]这10个数字。目前想到的有两种:
- 点图 将[0-9]10个数字,每个数字赋一个颜色,然后一次绘制圆点。
- 线段图 [0-9]10个数字每个数字赋一个颜色和角度,绘制收尾相接的线段。
点图
点图的绘制相对简单,首先定义颜色:
# 圆点边线颜色
color = ['gold', 'goldenrod', 'red', 'firebrick', 'mediumvioletred', 'darkorchid', 'royalblue', 'lightseagreen', 'mediumseagreen', 'olivedrab']
# 圆点填充颜色
color_fill = ['khaki', 'moccasin', 'lightcoral', 'lightsalmon', 'orchid', 'mediumpurple', 'skyblue', 'aquamarine', 'lightgreen', 'palegreen']
数字[0-9]当作颜色的下标索引获取颜色,绘制单个圆点的代码如下:
def draw_dot(n: int, c: int):
""" 绘制圆点
:param n: 小数位数值
:param c: 第几位
:return: None
"""
t.color(color_fill[n])
t.begin_fill()
t.circle(10)
t.end_fill()
t.color(color[n])
t.circle(10)
pos = t.pos()
绘制完一个圆点后,turtle移动到下一个位置,这里我设置为每40位换一行:
def move(c: int):
""" 移动到下一位置
:param c: 小数点后第几位
:return: None
"""
pos = t.pos()
t.penup()
if c % 40 == 0: #每40位换一行
t.goto(-600, pos[1] - 30)
else:
t.goto(pos[0] + 30, pos[1])
t.pendown()
最后我们只要读取 π \pi π 的小数位,循环绘制圆点即可:
import turtle
turtle.setup(1.0, 1.0)
t = turtle.Turtle()
t.hideturtle()
t.pensize(2)
t.penup()
t.goto(-600, 400)
t.pendown()
t.speed(0)
# 绘制整数位3
count = 1
num = 3
draw_dot(num, count)
move(count)
# 循环绘制小数位
with open('圆周率前100万位.txt') as f:
for i in range(28): # 绘制28*50=1400位
word = f.readline().strip()
for a in word:
num = int(a)
count += 1
draw_dot(num, count)
move(count)
f.close()
turtle.done()
最终效果如下图:
线段图
有了点图的基础,线段图的绘制相对简单。直接上代码:
import turtle
turtle.setup(1.0, 1.0)
t = turtle.Turtle()
t.hideturtle()
t.pensize(2)
t.pendown()
t.left(90)
t.speed(0)
color = ['gold', 'goldenrod', 'red', 'firebrick', 'mediumvioletred', 'darkorchid', 'royalblue', 'lightseagreen', 'mediumseagreen', 'greenyellow']
# 绘制整数位3
last_num = 3
t.color(color[last_num])
t.right(last_num * 36)
t.forward(40)
# 循环绘制小数位
with open('圆周率前100万位.txt') as f:
for i in range(100):
word = f.readline().strip()
for a in word:
current_num = int(a)
t.color(color[current_num])
angle = (current_num - last_num) * 36
t.right(angle)
t.forward(20)
last_num = current_num
f.close()
turtle.done()
最终效果:
结论
怎么样?很神奇吧?如果你有更好的可视化思路,欢迎留言评论交流。
最后,祝大家 π \pi π Day快乐!