问题描述
问题:
我正在寻找一个包罗万象的函数,我可以用它来计算 任何 多项式函数在 x 处的切线。我对使用的语言无动于衷,尽管更喜欢 JavaScript 或 Python!我应该能够以 a + bx + cx^2 + dx^3 ... 等格式传入任何 x 值和系数数组。
示例函数格式:
function findTangent(x,coefficients) {
// Do differential calculus here.
return [tangentIntercept,tangentSlope]
}
示例功能测试:
假设我有函数 y = 2 + 7x + 5x^2 + x^3 并且我想在 x = -2 处找到切线.我可以像这样调用这个函数,findTangent(-2,[2,7,5,1])
并得到一个像这样的返回值,[-2,-1]
代表切线,y = -2 - x。
注意事项:
我在 Math Stackexchange 和 Google 搜索中寻找答案,但所有结果都采用数学语法而不是代码。我想要一个程序化的解决方案,我更喜欢循环和 if 语句,而不是有趣的符号和数学术语!
解决方法
好的,经过一天的努力,我想我已经在 JavaScript 和 Python 中找到了解决方案!
function findTangent(x,coefficients) {
let slope = 0
let intercept = coefficients[0]
for (let i = 1; i < coefficients.length; i++) {
slope += coefficients[i] * i * Math.pow(x,i - 1)
intercept += coefficients[i] * Math.pow(x,i)
}
return [intercept - slope * x,slope]
}
def find_tangent(x,coefficients):
slope = 0
intercept = coefficients[0]
for i,coefficient in enumerate(coefficients):
if i != 0:
slope += coefficient * i * pow(x,i - 1)
intercept += coefficient * pow(x,i)
return [intercept - slope * x,slope]
我已经针对 Symbolab Tangent Calculator 测试了结果,它们似乎没问题,但是如果您发现任何错误,请告诉我!此外,我希望看到其他语言的结果因此,如果您有此处未提及的首选语言,请随时发布!
,由于您询问了其他语言,这里是一个 C 函数,用于计算多项式在某一点的导数(和值)。我推荐的方法可以用于任何语言。
double pol_eval_d( double x,int deg,const double* c,double* pdp)
{
double p = c[deg];
double dp = 0.0;
for( int d=deg-1; d>=0; --d)
{ dp = fma( dp,x,p);
p = fma( p,c[d]);
}
*pdp = dp;
return p;
}
此函数采用 x 值、多项式的次数和系数,并返回多项式在 x 处的值及其在 *pdp 中的导数值。
系数是 c[0](幂 0)、c[1](幂 1)、.. 和 c[deg](幂 deg)。
它调用(C 数学库)函数 fma,为此
fma(x,y,z) = x*y+z,except that it is evaluated with extra precision.
如果你没有这样的函数,你可以用上面的表达式替换调用,虽然你会失去一点准确性。
使用的方法是霍纳的方法。这通常比评估多项式的其他方法更快、更准确。
为了解释它是如何工作的,首先考虑我们不想要导数的情况。然后就可以写
double pol_eval( double x,const double* c)
{
double p = c[deg];
for( int d=deg-1; d>=0; --d)
{ p = fma( p,c[d]);
}
return p;
}
如果我们逐步了解二次方程会发生什么,并用它们的数学等价物替换 fma 调用,我们会得到
p = c[2]
p = p*x + c[1]
p = p*x + c[0]
这是我们评估过的
c[0]+x*c[1]+x*x*c[2]
由
c[0] + x*(c[1] + x*c[2])
这是霍纳的方法。
为了计算导数,我们对 pol_eval 中的每一项进行微分。最初 p 是一个常数,所以它的导数是 0。然后当我们更新 p 时
p = fma( p,c[d]);
或者用数学术语
p = p*x + c[d];
我们使用乘积规则来区分,所以因为 c[d] 是一个常数
dp = dp*x + p
并注意我们必须在更新 p 之前这样做
,使用允许符号微分的 Python Sympy
代码
from sympy import Function,Symbol
def polynomial(coeficents,degrees,x):
'''
Evaluate polynomial
Example
coefficients = [1,2,4]
degrees = [2,1,0]
corresponds to polynomial x^2 + 2*x + 4
'''
return sum([coeficents[i]*x**degrees[i] for i in range(len(coeficents))])
# Using OP polynomial
coefficients = [1,5,7,2]
degrees = [3,0]
print(polynomial(coefficients,-2)) # Output: 15
# Create symbolic polynomial in x
# Define symbolic variable x
x = Symbol('x') # symbolic variable x
# Create polynomial in x for OP polynomial
poly = polynomial(coefficients,x)
print(poly) # Output: x**3 + 5*x**2 + 7*x + 2
# Evaluate at x = -2
print(poly.subs(x,-2)) # Output: 7 (i.e. substitute x for 1 in equation)
####################################################
# Symbolic differentiation of polynomial 'poly'
####################################################
diff_poly = poly.diff(x)
print(diff_poly) # Output: 3*x**2 + 10*x + 7 (derivative of polynomial)
# Evaluate derivative at x = -2
print(diff_poly.subs(x,-2)) # Output: -1 (derivate at x = -1)