好的,所以基本上我的问题是从“解决纸上”的数学问题转变为通过编程解决问题。让我解释一下:我想知道是否可以在为变量赋值之前对变量执行操作。就像我有类似(1-x)**n
之类的东西一样,我可以先给一个值赋值,然后将它转换为特定度的特定值,然后给x一个或多个值。如果我不够清楚:如果n = 2,我可以首先转换1-2x+x**2
形式的等式,然后在下一步中处理x值吗?
我想写一个用于计算和绘制第n度Bezier曲线的代码。我正在使用Bernstein多项式,所以我意识到方程由3部分组成:第一部分是多项式系数,它们都是Pascal三角形的一部分;我正在计算这些并将它们放在一个列表中。第二部分是控制点的坐标,也是某种系数,并将它们放在单独的列表中。现在是困难的部分:方程式的一部分有一个变量.Bernsteins正在使用barocentric坐标(意思是u和1-u)。这部分方程的第N度公式是:
u**i *(1-u)**(n-i)
其中n是曲线度,I从0-> n开始,U是变量.U是acctualy规范化变量,意味着它的值可以从0到1,我想稍后在一定数量的步骤中对它进行迭代(比如1000)。但问题是,如果我尝试使用上面提到的等式,我会不断收到错误,因为Python不知道如何处理uI所教的嵌套循环,其中第一个会将u的值从0改为1,第二个从0到n处理上面提到的等式,但不确定它是否是正确的解决方案,并且不知道如何去研究结果。你怎么看? PS:我没有上传代码,因为我遇到问题的部分甚至无法启动,而且,我认为但可能是错误的,它与代码的其余部分分开;但如果你认为它可以帮助解决问题我可以上传它。
答案 0 :(得分:3)
您可以使用高阶函数,即返回函数的函数,例如
def Bernstein(n,i):
def f(t):
return t**i*(1.0-t)**(n-i)
return f
您可以像这样使用
b52 = Bernstein(5,2)
val = b52(0.74)
但您宁愿使用列表
Bernstein_ni = [Bernstein(n,i) for i in range(n+1)]
用于更高阶函数以构建Bezier曲线函数
def mk_bezier(Px,Py):
"Input, lists of control points, output a function of t that returns (x,y)"
n = len(Px)
binomials = {0:[1], 1:[1,1], 2:[1,2,1],
3:[1,3,3,1], 4:[1,4,6,4,1], 5:[1,5,10,10,5,1]}
binomial = binomials[n-1]
bPx = [b*x for b,x in zip(binomial,Px)]
bPy = [b*y for b,y in zip(binomial,Py)]
bns = [Bernstein(n-1,i) for i in range(n)]
def f(t):
x = 0 ; y = 0
for i in range(n):
berns = bns[i](t)
x = x + bPx[i]*berns
y = y + bPy[i]*berns
return x, y
return f
最终,在您的程序中,您可以像这样使用函数工厂
linear = mk_bezier([0.0,1.0],[1.0,0.0])
quadra = mk_bezier([0.0,1.0,2.0],[1.0,3.0,1.0])
for t in (0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0):
l = linear(t) ; q = quadra(t)
print "%3.1f (%6.4f,%6.4f) (%6.4f,%6.4f)" % (t, l[0],l[1], q[0],q[1])
这是测试输出
0.0 (0.0000,1.0000) (0.0000,1.0000)
0.1 (0.1000,0.9000) (0.2000,1.3600)
0.2 (0.2000,0.8000) (0.4000,1.6400)
0.3 (0.3000,0.7000) (0.6000,1.8400)
0.4 (0.4000,0.6000) (0.8000,1.9600)
0.5 (0.5000,0.5000) (1.0000,2.0000)
0.6 (0.6000,0.4000) (1.2000,1.9600)
0.7 (0.7000,0.3000) (1.4000,1.8400)
0.8 (0.8000,0.2000) (1.6000,1.6400)
0.9 (0.9000,0.1000) (1.8000,1.3600)
1.0 (1.0000,0.0000) (2.0000,1.0000)
我认为正确的方法是在模块级别,使用顶级排序 - defaultdictionary
memoizes 所有不同的执行实际计算所需的列表,但defaultdict
没有将变量传递给其default_factory
,我感觉不像是dict
的子类(不是现在)为了这个答案,主要原因是我之前从未进行过分类......
你说功能度是主要参数吗?但它是由控制点列表的长度隐含地定义的......
N = user_input()
P0x = user_input()
P0y = user_input()
PNx = user_input()
PNy = user_input()
# code that computes P1, ..., PNminus1
orderN = mk_bezier([P0x,P1x,...,PNminus1x,PNx],
[P0y,P1y,...,PNminus1y,PNy])
x077, y077 = orderN(0.77)
但客户永远是对的,所以如果你声明它的做法与你的期望不同,我将永远不会再次试图说服你,我的解决方案适合你。
答案 1 :(得分:1)
有用于进行符号数学的Python包,但使用Numpy中的一些polynomial functions可能更容易。这些函数使用多项式表示为系数数组的约定,从最低阶系数开始。因此,多项式a*x^2 + b*x + c
将表示为array([c, b, a])
。
一些例子:
In [49]: import numpy.polynomial.polynomial as poly
In [50]: p = [-1, 1] # -x + 1
In [51]: p = poly.polypow(p, 2)
In [52]: p # should be 1 - 2x + x^2
Out[52]: array([ 1., -2., 1.])
In [53]: x = np.arange(10)
In [54]: poly.polyval(x, p) # evaluate polynomial at points x
Out[54]: array([ 1., 0., 1., 4., 9., 16., 25., 36., 49., 64.])
你可以用类似的方式计算你的伯恩斯坦多项式(仍然缺少二项式系数):
In [55]: def Bernstein(n, i):
...: part1 = poly.polypow([0, 1], i) # (0 + u)**i
...: part2 = poly.polypow([1, -1], n - i) # (1 - u)**(n - i)
...: return poly.polymul(part1, part2)
In [56]: p = Bernstein(3, 2)
In [57]: p
Out[57]: array([ 0., 0., 1., -1.])
In [58]: poly.polyval(x, p) # evaluate polynomial at points x
Out[58]: array([ 0., 0., -4., -18., ..., -448., -648.])