花车和decimal.Decimal小数位问题花车和decimal.Decimal小数位问题(Dec

2019-05-12 04:01发布

我似乎失去了很多的精度浮点数。

例如,我需要解决一个矩阵:

4.0x -2.0y 1.0z =11.0
1.0x +5.0y -3.0z =-6.0
2.0x +2.0y +5.0z =7.0

这是我使用从文本文件导入矩阵的代码:

f = open('gauss.dat')
lines =  f.readlines()
f.close()

j=0
for line in lines:
    bits = string.split(line, ',')
    s=[]
    for i in range(len(bits)):
        if (i!= len(bits)-1):
            s.append(float(bits[i]))
            #print s[i]
    b.append(s)
    y.append(float(bits[len(bits)-1]))

我需要用高斯 - 塞德尔所以我需要重新安排的x,y和z的方程组的求解:

x=(11+2y-1z)/4
y=(-6-x+3z)/5
z=(7-2x-2y)/7

下面是我用它来重新排列方程中的代码。 b是系数矩阵和y是答案向量:

def equations(b,y):
    i=0
    eqn=[]
    row=[]
    while(i<len(b)):
        j=0
        row=[]
        while(j<len(b)):
            if(i==j):
                row.append(y[i]/b[i][i])
            else:
                row.append(-b[i][j]/b[i][i])
            j=j+1
        eqn.append(row)
        i=i+1
    return eqn

不过我找回答案并不精确到小数点后一位。

例如,在重新安排从上面的第二个方程,我应该得到:

y=-1.2-.2x+.6z

我得到的是:

y=-1.2-0.20000000000000001x+0.59999999999999998z

这看起来可能不是一个大问题,但是当你提高的数量非常高的功率误差是相当大的。 有没有解决的办法? 我试过Decimal类,但它不与权力很好地工作(即Decimal(x)**2 )。

有任何想法吗?

Answer 1:

我不是小数类足够的熟悉来帮助你,但你的问题是由于小数往往不准确表示二进制,所以你看到的是最接近的可能近似的事实; 有没有办法避免这个问题,而无需使用特殊类(如十进制,可能)。

EDIT:关于小数点类什么是不适合你正常工作? 只要我开始一个字符串,而不是浮动,权力,似乎工作的罚款。

>>> import decimal
>>> print(decimal.Decimal("1.2") ** 2)
1.44

该模块文档说明了的和使用的需要decimal.Decimal很清楚,你应该检查出来,如果你还没有。



Answer 2:

IEEE浮点是二进制的,不是小数。 没有固定长度的二进制分数,这正是0.1,或它们的任何倍数。 是重复分数,像在十进制1/3。

请阅读什么每台计算机科学家应该知道关于浮点运算

除了一个小数类的其它选项

  • 使用的Common Lisp或Python的2.6或确切有理数另一种语言

  • 转换双打使用关闭有理数,例如, FRAP



Answer 3:

首先,你的输入可以简化很多。 你并不需要阅读和分析的文件。 你可以只申报在Python符号的对象。 EVAL文件。

b = [
    [4.0, -2.0,  1.0],
    [1.0, +5.0, -3.0],
    [2.0, +2.0, +5.0],
]
y = [ 11.0, -6.0, 7.0 ]

其次,Y = -1.2-0.20000000000000001x + 0.59999999999999998z是不寻常的。 还有用二进制表示没有确切表示为0.2或0.6。 因此,所显示的值是原来不准确表示的十进制近似值。 这些是几乎所有种类的浮点处理器存在的事实。

您可以尝试的Python 2.6 分数模块。 这里有一个旧的理性包,可能的帮助。

是的,提高浮点数到权力增加了错误。 因此,你必须确保避免使用浮点数的最右边的位置,因为这些位大多噪音。

当显示浮点数,你必须适当轮他们以避免看到噪音位。

>>> a
0.20000000000000001
>>> "%.4f" % (a,)
'0.2000'


Answer 4:

我想告诫像这样的任务十进制模块。 其目的是真是越来越处理现实世界的十进制数(如配套人类簿记惯例),具有有限的精度,不执行准确精度数学。 有正如有二进制数小数不能准确地表示,以10进制执行算术也比替代品慢得多。

相反,如果你想确切的结果,你应该使用合理的算术。 这些将代表数字作为计数器/ denomentator对,因此可以完全代表所有的有理数。 如果你只使用乘法和除法(而不是像平方根,可导致无理数的行动),你永远不会丢失精度。

正如其他人所说,蟒蛇2.6将有一个内置的理性型,但注意,这不是一个真正的高性能的实现-为您更好地使用图书馆般的速度gmpy 。 只需更换您的来电浮动()来gmpy.mpq()和你的代码现在应该给予确切的结果(尽管你可能要格式化的结果彩车用于显示目的)。

这里是你的代码稍微收拾版本加载,将使用gmpy有理数,而不是一个矩阵:

def read_matrix(f):
    b,y = [], []
    for line in f:
        bits = line.split(",")
        b.append( map(gmpy.mpq, bits[:-1]) )
        y.append(gmpy.mpq(bits[-1]))
    return b,y


Answer 5:

这不是一个回答你的问题,但相关的:

#!/usr/bin/env python
from numpy import abs, dot, loadtxt, max
from numpy.linalg import solve

data = loadtxt('gauss.dat', delimiter=',')
a, b = data[:,:-1], data[:,-1:]
x = solve(a, b) # here you may use any method you like instead of `solve`
print(x)
print(max(abs((dot(a, x) - b) / b))) # check solution

例:

$ cat gauss.dat
4.0, 2.0, 1.0, 11.0
1.0, 5.0, 3.0, 6.0 
2.0, 2.0, 5.0, 7.0

$ python loadtxt_example.py
[[ 2.4]
 [ 0.6]
 [ 0.2]]
0.0


Answer 6:

另请参阅什么是浮点错误的一个简单的例子 ,在这里左右,其中有一些答案。 一个我给实际使用Python作为例子语言...



文章来源: Decimal place issues with floats and decimal.Decimal