使用 numpy 乘法后多项式值错误
Wrong polynomial value after multiplication by using numpy
在下面的脚本中,我将许多多项式相乘并尝试通过设置 x=1855 来获得正确的值。
答案必须为零,因为乘法中的一个方程是
x-1855 但在乘以第七个 times.The 结果显示多项式值和多项式后答案远大于零。
我在想它是否在某处溢出但我不确定。
我需要help.Thank你~
from matplotlib import pyplot as plt
import csv
import math
import numpy as np
x=np.array([1860, 1855, 1844, 1828, 1550, 1507, 1496, 1486, 1485, 1480, 1475, 1442,
1032, 950, 593, 543, 499, 243, 211, 200, 189, 173, 168, 152, 141, 140,
124, 97, 87, 76, 70, 65, 59, 49, 43, 38,27, 22, 11,],'d')
p1=1
for i in range(1,39):
p2 = np.poly1d([1,-x[i]])
p1 = np.polymul(p1,p2)
print(p2)
print(p1(1855))
多项式(前8个)
1 x - 1855, 1 x - 1844 , 1 x - 1828 , 1 x - 1550 ,1 x - 1507 ,1 x - 1496, 1 x - 1486,1 x - 1485
乘法
1 x - 1855 -->first
2
1 x - 3699 x + 3.421e+06 -->second
3 2
1 x - 5527 x + 1.018e+07 x - 6.253e+09 -->third
4 3 2
1 x - 7077 x + 1.875e+07 x - 2.204e+10 x + 9.692e+12 -->forth
5 4 3 2
1 x - 8584 x + 2.941e+07 x - 5.029e+10 x + 4.29e+13 x - 1.461e+16 -->fifth
6 5 4 3 2
1 x - 1.008e+04 x + 4.226e+07 x - 9.429e+10 x + 1.181e+14 x - 7.878e+16 x + 2.185e+19
-->sixth
7 6 5 4 3
1 x - 1.157e+04 x + 5.723e+07 x - 1.571e+11 x + 2.583e+14 x
2
- 2.543e+17 x + 1.389e+20 x - 3.247e+22 --seventh
8 7 6 5 4
1 x - 1.305e+04 x + 7.441e+07 x - 2.421e+11 x + 4.915e+14 x
3 2
- 6.378e+17 x + 5.166e+20 x - 2.388e+23 x + 4.822e+25 -->eighth
....
结果
when x=1855
first one=first two multiplication=...=first six multiplication=0
first seven multiplication=37748736.0
first eight multiplication=558345748480.0
不是溢出,是fp分辨率不够
让我们来看看您首先看到错误结果的七个因素:
>>> import numpy as np
>>> import functools as ft
>>>
>>> x=np.array([1860, 1855, 1844, 1828, 1550, 1507, 1496, 1486, 1485, 1480, 1475, 1442,
... 1032, 950, 593, 543, 499, 243, 211, 200, 189, 173, 168, 152, 141, 140,
... 124, 97, 87, 76, 70, 65, 59, 49, 43, 38,27, 22, 11,],'d')
>>>
>>> L = np.c_[np.ones_like(x), -x]
>>> first7 = ft.reduce(np.polymul, L[:7])
>>> first7
array([ 1.00000000e+00, -1.19400000e+04, 6.10047450e+07, -1.72890531e+11,
2.93522255e+14, -2.98513911e+17, 1.68387944e+20, -4.06415732e+22])
让我们关注最后一个系数。我们可以使用 np.nextafter
在任一方向上获得下一个可表示的数字。
>>> first7[-1] - np.nextafter(first7[-1], 0)
-8388608.0
>>> first7[-1] - np.nextafter(first7[-1], 2 * first7[-1])
8388608.0
正如我们所见,分辨率比 1 差很多,这意味着系数实际上是不准确的。
如果你只对整数系数和参数感兴趣,可以使用Python整数来避免这个问题(以牺牲性能为代价):
>>> Li = L.astype(int).astype(object)
>>> fullprod = ft.reduce(np.polymul, Li)
>>> np.polyval(fullprod, np.array(1855, dtype=object))
0
如果您需要浮点数,请考虑使用类似 bigfloat
的东西(sympy
也可以)。
>>> from bigfloat import BigFloat, setcontext, Context
# set precision (1000 is probably way too much)
>>> setcontext(Context(precision=1000))
# convert array elements
>>> Lb = np.frompyfunc(BigFloat, 1, 1)(L)
# compute product
>>> fullprod = ft.reduce(np.polymul, Lb)
# evaluate
>>> np.polyval(fullprod, BigFloat(1855))
BigFloat.exact('0', precision=1000)
在下面的脚本中,我将许多多项式相乘并尝试通过设置 x=1855 来获得正确的值。
答案必须为零,因为乘法中的一个方程是 x-1855 但在乘以第七个 times.The 结果显示多项式值和多项式后答案远大于零。
我在想它是否在某处溢出但我不确定。 我需要help.Thank你~
from matplotlib import pyplot as plt
import csv
import math
import numpy as np
x=np.array([1860, 1855, 1844, 1828, 1550, 1507, 1496, 1486, 1485, 1480, 1475, 1442,
1032, 950, 593, 543, 499, 243, 211, 200, 189, 173, 168, 152, 141, 140,
124, 97, 87, 76, 70, 65, 59, 49, 43, 38,27, 22, 11,],'d')
p1=1
for i in range(1,39):
p2 = np.poly1d([1,-x[i]])
p1 = np.polymul(p1,p2)
print(p2)
print(p1(1855))
多项式(前8个)
1 x - 1855, 1 x - 1844 , 1 x - 1828 , 1 x - 1550 ,1 x - 1507 ,1 x - 1496, 1 x - 1486,1 x - 1485
乘法
1 x - 1855 -->first
2
1 x - 3699 x + 3.421e+06 -->second
3 2
1 x - 5527 x + 1.018e+07 x - 6.253e+09 -->third
4 3 2
1 x - 7077 x + 1.875e+07 x - 2.204e+10 x + 9.692e+12 -->forth
5 4 3 2
1 x - 8584 x + 2.941e+07 x - 5.029e+10 x + 4.29e+13 x - 1.461e+16 -->fifth
6 5 4 3 2
1 x - 1.008e+04 x + 4.226e+07 x - 9.429e+10 x + 1.181e+14 x - 7.878e+16 x + 2.185e+19
-->sixth
7 6 5 4 3
1 x - 1.157e+04 x + 5.723e+07 x - 1.571e+11 x + 2.583e+14 x
2
- 2.543e+17 x + 1.389e+20 x - 3.247e+22 --seventh
8 7 6 5 4
1 x - 1.305e+04 x + 7.441e+07 x - 2.421e+11 x + 4.915e+14 x
3 2
- 6.378e+17 x + 5.166e+20 x - 2.388e+23 x + 4.822e+25 -->eighth
....
结果
when x=1855
first one=first two multiplication=...=first six multiplication=0
first seven multiplication=37748736.0
first eight multiplication=558345748480.0
不是溢出,是fp分辨率不够
让我们来看看您首先看到错误结果的七个因素:
>>> import numpy as np
>>> import functools as ft
>>>
>>> x=np.array([1860, 1855, 1844, 1828, 1550, 1507, 1496, 1486, 1485, 1480, 1475, 1442,
... 1032, 950, 593, 543, 499, 243, 211, 200, 189, 173, 168, 152, 141, 140,
... 124, 97, 87, 76, 70, 65, 59, 49, 43, 38,27, 22, 11,],'d')
>>>
>>> L = np.c_[np.ones_like(x), -x]
>>> first7 = ft.reduce(np.polymul, L[:7])
>>> first7
array([ 1.00000000e+00, -1.19400000e+04, 6.10047450e+07, -1.72890531e+11,
2.93522255e+14, -2.98513911e+17, 1.68387944e+20, -4.06415732e+22])
让我们关注最后一个系数。我们可以使用 np.nextafter
在任一方向上获得下一个可表示的数字。
>>> first7[-1] - np.nextafter(first7[-1], 0)
-8388608.0
>>> first7[-1] - np.nextafter(first7[-1], 2 * first7[-1])
8388608.0
正如我们所见,分辨率比 1 差很多,这意味着系数实际上是不准确的。
如果你只对整数系数和参数感兴趣,可以使用Python整数来避免这个问题(以牺牲性能为代价):
>>> Li = L.astype(int).astype(object)
>>> fullprod = ft.reduce(np.polymul, Li)
>>> np.polyval(fullprod, np.array(1855, dtype=object))
0
如果您需要浮点数,请考虑使用类似 bigfloat
的东西(sympy
也可以)。
>>> from bigfloat import BigFloat, setcontext, Context
# set precision (1000 is probably way too much)
>>> setcontext(Context(precision=1000))
# convert array elements
>>> Lb = np.frompyfunc(BigFloat, 1, 1)(L)
# compute product
>>> fullprod = ft.reduce(np.polymul, Lb)
# evaluate
>>> np.polyval(fullprod, BigFloat(1855))
BigFloat.exact('0', precision=1000)