【方法1】,直接把$x=\frac{1}{2}$代入上面的表达式,可以计算出结果。如下面的python程序,这个方法要计算10次乘法,4次加法。
In [7]:
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可以确保最后结果保持分数的形式
【方法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来实现的采用嵌套乘法计算的函数。
In [8]:
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]))
53 ➗ 2 = 26 余 1
26 ➗ 2 = 13 余 0
13 ➗ 2 = 6 余 1
6 ➗ 2 = 3 余 0
3 ➗ 2 = 1 余 1
1 ➗ 2 = 0 余 1
因此$(53)_{10} = (110101)_2$
0.7 ✖ 2 = 0.4 --> 1
0.4 ✖ 2 = 0.8 --> 0
0.8 ✖ 2 = 0.6 --> 1
0.6 ✖ 2 = 0.2 --> 1
0.2 ✖ 2 = 0.4 --> 0
0.4 ✖ 2 = 0.8 --> 0
0.8 ✖ 2 = 0.6 --> 1
...
最后会形成重复的位,表示为:$(0.7)_{10} = (0.101100110...)_2=(0.1\overline{0110})_2$
整数部分:以2为基建立多项式,比如$(10101)_2$可以转为: $$1\times 2^4+0\times 2^3+1\times 2^2+0\times 2^1+1\times 2^0=(21)_{10} \notag $$
小数部分:以$\frac{1}{2}$为基建立多项式,比如$(0.1011)_2$转为: $$ 1\times\left(\frac{1}{2}\right)^1+0\times\left(\frac{1}{2}\right)^2+1\times\left(\frac{1}{2}\right)^3+1\times\left(\frac{1}{2}\right)^4 = \left(\frac{11}{16}\right)_{10} $$
注意当小数为重复出现的循环小数时,可以利用2乘的平移性质的技巧:
当小数部分全是循环小数时,比如 $x=(0.\overline{1011})_2$ ,由于小数后有4位小数循环,所以把 $x\cdot 2^4$,得到: $$ \begin{align*} 2^4x &=1011.\overline{1011} \\ x &=0000.\overline{1011} \end{align*} \notag $$,上下相减得到:$(2^4-1)x=(1011)_2=(11)_{10}$,求解出$x$,转换为十进制,得到:$x=(0.\overline{1011})_2=\left(\frac{11}{15}\right)_{10}$
当小数部分有部分是循环小数时,比如 $x=(0.10\overline{101})_2$ ,把 $x\cdot 2^2$,得到 $y=2^2x=(10.\overline{101})_2 $, 取$y$的分数部分,记为$z=0.\overline{101}$,按前面所述进行计算: $$ \begin{align*} 2^3z &=101.\overline{101} \\ z &=000.\overline{101} \end{align*} \notag $$,上下相减得到:$(2^3-1)z=(101)_2=(5)_{10}$,求解出$7z=5, y=2+z=2+\frac{5}{7}, x=\frac{y}{2^2}=\frac{19}{28}$
二进制 | 八进制 | 二进制 | 十六进制 |
---|---|---|---|
000 | 0 | 0000 | 0 |
001 | 1 | 0001 | 1 |
010 | 2 | 0010 | 2 |
011 | 3 | 0011 | 3 |
100 | 4 | 0100 | 4 |
101 | 5 | 0101 | 5 |
110 | 6 | 0110 | 6 |
111 | 7 | 0111 | 7 |
- | - | 1000 | 8 |
- | - | 1001 | 9 |
- | - | 1010 | A |
- | - | 1011 | B |
- | - | 1100 | C |
- | - | 1101 | D |
- | - | 1110 | E |
- | - | 1111 | F |
二进制转八进制的例子: $ \underline{101}\:\underline{011}\:\underline{110} \Leftrightarrow 536$
二进制转十六进制的例子: $ \underline{1101}\:\underline{0011}\:\underline{1100} \Leftrightarrow D3C$
精度(总位数) | 符号($\pm$)位 | 指数位 | 尾数位(有效二进制数位) |
---|---|---|---|
单精度(32bit) | 1 | 8 | 23 |
双精度(64bit) | 1 | 11 | 52 |
长双精度(80bit) | 1 | 15 | 64 |
浮点数的表示:$\pm 1.bbb...b\times 2^p$,其中$N$个$b$是$0$或者$1$,$p$是一个$M$位的二进制数表示指数,最左边的一位必须是$1$,意味着每个保存的浮点数必须转换为二进制的小数,只保留一位的小数点左边的$1$,转换为指数的形式。
比如:十进制的 $92.6$ ,转换为小数的二进制表示: $\underline{101}\:\underline{1100}.\overline{1001} \to +1.\underline{01}\:\underline{1100}\:\underline{1001}...\times 2^6 \to +1.\underline{01}\:\underline{1100}\:\underline{1001}...\times 2^{\underline{110}}$,对于单精度的类型,实际存储的内容如下:
符 | 指数位(8位) | 尾数位(23位) |
---|---|---|
$\underline{0}$ | $\underline{0000}\:\underline{0110}$ | $\underline{01}\:\underline{1100}\:\underline{1001}\:\underline{1001}\:\underline{1001}\:\underline{1001}\:\underline{1}$ |