【发布时间】:2021-10-15 14:09:42
【问题描述】:
感谢 Veritasium 关于该主题的精彩视频,我正计划快速复制他在视频中显示的动画,其中数字上下跳动直到达到数字 1,具体取决于初始数字。
下面我想出了一个实现动画的代码版本。但是我在构建代码时有一个疑问和困惑。
我发现如果我不将 y-data 初始化为 y=np.empty(100) 而是使用空列表,则会抛出错误 list assignment index out of range
所以我很困惑为什么我不能从一个空列表开始,因为我知道,取决于y_start 的值,len(y) 会有所不同。如果我可以将这些计算出的 y 值收集到一个列表中(稍后将它们转换为数组),那么我不必去整个夜场设置plt.xlim(1,100)(相反,我可以设置plt.xlim(0,len(y))也是由于最终 y 数据中可能剩余 0.0 值,我必须在 if 语句中添加附加条件(and 之后的第二个)-> if y[i] % 2 == 0 and y[i] != 0: 否则,即使在 y 达到值 1 后它也会变得混乱......
此外,我想添加 y-data 的值显示在每个单独的点之上,但我不知道如何在代码中实现它......如果有人能帮助解决这个问题,我将不胜感激让动画看起来更“完整”!
这是我测试过的代码
import numpy as np
from matplotlib.animation import FuncAnimation
from matplotlib import pyplot as plt
def odd(num):
return (num*3)+1
def even(num):
return num // 2
y_start = 33
x = np.linspace(0, 100, 100)
# y = []
def collatz():
y = np.empty(100)
y[0] = y_start
for i in range(0,100):
if y[i] % 2 == 0 and y[i] != 0:
y[i+1] = even(y[i])
else:
y[i+1] = odd(y[i])
if y[i+1] == 1:
break
return y
y = collatz()
fig = plt.figure()
plt.xlim(1,100)
plt.ylim(1,max(y))
draw, = plt.plot([],[])
def update(idx):
draw.set_data(x[:idx], y[:idx])
return draw,
a = FuncAnimation(fig, update, frames=len(x), interval=90)
plt.show()
所以,我的问题是,
为什么从一个空列表开始包含计算的 y 会失败?
另外,在早期版本中,在 collatz 函数定义中,我的代码是这样的:
def collatz():
y = np.empty(100)
y[0] = y_start
for i in range(0,100):
while y[i] != 1:
if y[i] % 2 == 0 and y[i] != 0:
y[i+1] = even(y[i])
else:
y[i+1] = odd(y[i])
if y[i+1] == 1:
break
return y
编译卡住了,代码好像在无限循环……不知道是不是while statement的用法?我应该怎么做/添加来纠正它?
【问题讨论】:
-
for循环中的while可能会使整个事情崩溃?让我们循环一下:
i = 0=>y[0] = 33,你到达了odd()函数。我猜你永远在while中循环?因为i没有增加(也不应该手动)。删除while可能会解决您的问题? -
顺便说一句,可能还有第二个问题。如果您的循环到达
i = 99,您将查找y的索引100,这也会产生错误 -
是的,
While循环对我来说总是一件棘手的事情......这就是为什么在上面有效的代码中,我删除了整个while loop感觉好像有更好/更智能的方法定义用于计算的 Collatz 函数以及构建 y 数组...
标签: python matplotlib animation