求任意多项式函数在 x 处的正切

Find the tangent of any polynomial function at x

问题:

我正在寻找可用于计算 any 多项式函数在 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]) 并得到一个像这样的 return 值,[-2, -1] 代表切线,y = -2 - x .

备注:

我在 Math Stackexchange 和 Google 搜索中寻找答案,但所有结果都是数学语法而不是代码。我想要一个程序化的解决方案,与有趣的符号和数学术语相比,我更喜欢循环和 if 语句!

好吧,经过一天的努力,我想我已经在 JavaScript Python!

中找到了解决方案

The JavaScript Solution:

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]

}

The Python Solution:

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 测试了结果,它们似乎没问题,但是 如果您发现任何错误,请告诉我! 另外,我很乐意查看其他语言的结果,所以如果您有此处未提及的首选语言,请不要犹豫 post!

使用 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, 2, 1, 0]
print(polynomial(coefficients, degrees, -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, degrees, 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)

既然你问过其他语言,这里有一个 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, x, c[d]);
    }
    *pdp = dp;
    return p;
}

此函数采用 x 值、多项式的次数和系数以及 returns 多项式在 x 处的值,以及它在 *pdp 中的导数的值。

系数是c[0](0次幂),c[1](1次幂),..和c[deg](幂次方)。

它调用(C 数学库)函数 fma,为此

fma(x,y,z) = x*y+z, except that it is evaluated with extra precision.

如果你没有这样的函数,你可以用上面的表达式替换调用,尽管你会失去一点准确性。

使用的方法是霍纳法。这通常比评估多项式的​​其他方法更快、更准确。

为了解释它是如何工作的,首先考虑我们不想要导数的情况。然后可以写

double  pol_eval( double x, int deg, const double* c)
{
double  p = c[deg];
    for( int d=deg-1; d>=0; --d)
    {   p = fma( p, x, 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, x, c[d]);

或数学术语

p = p*x + c[d];

我们使用乘积规则对其进行微分,因此由于 c[d] 是常数

dp = dp*x + p

并注意我们必须在更新 p

之前执行此操作

自动接受的答案很好,这是我的看法;

为了提高效率,可以将以下代码放在单个 .reduce() 语句下,但我想将其保留在扩展形式中以帮助说明;

function tangent(x,as){
  var y = as.reduce((p,c,i) => p+c*x**i),     // find the y value at x
      m = as.map((a,i) => a*i)                // find the derivative
            .reduce((p,c,i) => p+c*x**(i-1)); // find the slope m at x
  return [y-m*x,m];                           // find the line from y & m
}

var line = tangent(-2, [2, 7, 5, 1]);
console.log(`The equation of the tangent line is "y = ${line[1]}x${(Math.sign(line[0])+"")[0]}${Math.abs(line[0])}"`);