سؤال

يبدو أنني أفقد الكثير من الدقة مع العوامات.

على سبيل المثال أحتاج إلى حل مصفوفة:

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).

أيه أفكار؟

هل كانت مفيدة؟

المحلول

وأنا لست على دراية بما فيه الكفاية مع الطبقة العشرية لمساعدتك، ولكن يرجع مشكلتك إلى حقيقة أن الكسور العشرية يمكن في كثير من الأحيان لا تكون دقيقة ممثلة في ثنائي، لذلك ما ترونه هو أقرب تقريب ممكن؛ ليس هناك طريقة لتجنب هذه المشكلة دون استخدام فئة خاصة (مثل عشري، على الأرجح).

وEDIT: ماذا عن الطبقة عشرية لا يعمل بشكل صحيح بالنسبة لك؟ طالما أن أبدأ بسلسلة، بدلا من تعويم، يبدو أن القوى للعمل بشكل جيد.

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

وحدة الوثائق يفسر الحاجة إلى واستخدام decimal.Decimal واضح جدا، يجب عليك التحقق من ذلك إذا كنت لم تقم بعد.

نصائح أخرى

النقطة العائمة في IEEE هي ثنائية وليست عشرية.لا يوجد جزء ثنائي ذو طول ثابت يبلغ بالضبط 0.1، أو أي مضاعفات له.وهو كسر متكرر، مثل 1/3 في النظام العشري.

يرجى القراءة ما يجب أن يعرفه كل عالم كمبيوتر عن حساب النقطة العائمة

الخيارات الأخرى إلى جانب الفئة العشرية هي

  • باستخدام اللثغة المشتركة أو بايثون 2.6 أو لغة أخرى ذات مبررات دقيقة

  • تحويل الزوجي لإغلاق العقلاني باستخدام، على سبيل المثال، frap

أولا، الإدخال يمكن تبسيط الكثير. لا تحتاج لقراءة وتحليل ملف. يمكنك فقط أن يعلن الأشياء الخاصة بك في بيثون التدوين. وحدة التقييم الملف.

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 ]

والثانية، ص = -1.2-0.20000000000000001x + 0.59999999999999998z ليس من غير المألوف. ليس هناك تمثيل المحدد في تدوين ثنائي 0.2 أو 0.6. وبالتالي، فإن القيم المعروضة هي تقريبية العشرية الأصلي ليس بالضبط تمثيل. تلك هي صحيح للتو عن كل نوع المعالج الفاصلة العائمة هناك.

ويمكنك أن تجرب بيثون 2.6 كسور حدة. هناك على حزمة العقلانية القديمة التي قد تساعد.

نعم، ورفع أرقام الفاصلة العائمة للقوى يزيد من الأخطاء. ونتيجة لذلك، عليك أن تكون متأكدا من تجنب استخدام أقصى اليمين مواقف عدد الفاصلة العائمة، منذ هذه البتات هي في معظمها الضوضاء.

عند عرض أرقام الفاصلة العائمة، يجب عليك بشكل مناسب جولة لهم لتجنب رؤية بت الضوضاء.

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

ويهمني ان نحذر من وحدة عشرية للمهام من هذا القبيل. الغرض منه هو في الحقيقة أكثر التعامل مع الأرقام العشرية في العالم الحقيقي (على سبيل المثال. مطابقة ممارسات المحاسبة الإنسان)، بدقة متناهية، لا يؤدون بالضبط الرياضيات الدقة. هناك أعداد لا للتمثيل بالضبط في العشرية مثلما هناك في ثنائي، وأداء العمليات الحسابية في العشرية هو أيضا أبطأ بكثير من البدائل.

وبدلا من ذلك، إذا كنت تريد نتائج دقيقة يجب عليك استخدام الحساب العقلاني. وتمثل هذه الأرقام كزوج البسط / denomentator، لذلك يمكن أن يمثل بالضبط كل الأرقام عقلانية. إذا كنت فقط باستخدام الضرب والقسمة (بدلا من العمليات مثل الجذور التربيعية التي يمكن أن تؤدي إلى أرقام غير منطقية)، وأنك لن تفقد الدقة.

وكما ذكر آخرون، بيثون 2.6 سيكون له المدمج في نوع العقلاني، على الرغم من ملاحظة أن هذا ليس حقا تنفيذ الأداء العالي - لسرعة كنت أفضل استخدام مكتبات مثل <وأ href = "HTTP: / /gmpy.sourceforge.net/ "يختلط =" نوفولو noreferrer "> gmpy . مجرد استبدال المكالمات لتعويم () لgmpy.mpq () والتعليمات البرمجية الآن يجب أن تعطي نتائج دقيقة (على الرغم من أنك قد ترغب في تنسيق النتائج كما يطفو لأغراض العرض).

وهنا نسخة مرتب قليلا من التعليمات البرمجية لتحميل المصفوفة التي سوف تستخدم rationals 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

وانها ليست جوابا على سؤالك، ولكنها ذات صلة:

#!/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

وانظر أيضا ما هو مثال بسيط العائمة خطأ نقطة هنا اليوم SO، التي لديها بعض الإجابات. واحد أعطي في الواقع يستخدم بيثون كلغة سبيل المثال ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top