import sympy as sy
x=sy.symbols("x")
p=2*x**4+3*x**3-3*x*x+5*x-1
print(p.subs(x,1/2))
print(p.subs(x,sy.S.One*1/2)) #sy.S.One可以确保最后结果保持分数的形式

"""
Explanation: 第0章 基础知识

本章主要内容：
- 初等微积分和函数求值的一些基本思想
- 现代计算机运行机器算术的细节
- 有效数字
- 二进制数制系统，浮点的表达
- 舍入的通用法则和误差影响
0.1 多项式求值

对于多项式：
$$P(x)=2x^4+3x^3-3x^2+5x-1 \notag$$
当$x=\frac{1}{2}$时，如何才是计算上面表达式结果的最优方式？
【方法1】，直接把$x=\frac{1}{2}$代入上面的表达式，可以计算出结果。如下面的python程序，这个方法要计算10次乘法，4次加法。
End of explanation
"""


import numpy as np

'''
程序:嵌套乘法求多项式的值
参数: n: integer, 多项式的阶
      c: list, 多项式每一项的系数数组，第一个是常数项，长度为n+1个
      x: double, x的值
      r: double, 基点数组, 长度为n个
'''
def nest(n,c,x,r):
    y=c[-1]
    for i in range(1,n+1,1):
       y=y*(x-r[n-i])+c[n-i]
    return y

print(nest(4,[-1,5,-3,3,2],1/2,[0,0,0,0]))

"""
Explanation: 【方法2】，可以先算当$x=\frac{1}{2}$时，$a=x\cdot x, b=x^3=x^2\cdot x=ax, c=x^4=bx$，最后原来的多项式可以看作：
$$ P(x,a,b,c)=2c+3b-3a+5x-1 \notag$$
这样，所需要的乘法是7次，加法4次，相比方法1减少了3次乘法，当数据量大的时候，可以得到更快的结果。
【方法3】，把原多项式改写为：
$$P(x)=-1+x\cdot(5+x\cdot(-3+x\cdot(3+x\cdot 2))) \tag{0.2}$$
这样就只有4次乘法，4次加法。这种方法称为：嵌套乘法或者霍纳方法。一般的，$d$阶多项式可以通过$d$次乘法和$d$次加法来求值。
例如，对于标准形式下的多项式：$c_1+c_2x+c_3x^2+c_4x^3+c_5x^4$ 可以写为嵌套的形式：
$$c_1+x(c_2+x(c_3+x(c_4+xc_5))) \tag{0.4}$$
而更加一般的是下面考虑到基点$r_1,r_2,...$得到的形式：
$$c_1+(x-r_1)(c_2+(x-r_2)(c_3+(x-r_3)(c_4+(x-r_4)c_5))) \tag{0.5}$$
下面是用numpy来实现的采用嵌套乘法计算的函数。
End of explanation
"""


