lineer denklem çözümü

oy
35

Ben programlı C lineer denklem, Objective C, ya da (gerekirse) C ++ bir sistem çözmek gerekir.

İşte denklem bir örnek:

-44.3940 = a * 50.0 + b * 37.0 + tx
-45.3049 = a * 43.0 + b * 39.0 + tx
-44.9594 = a * 52.0 + b * 41.0 + tx

Bu, ben için en yakın sonucu elde etmek istiyorum a, bve tx.

Oluştur 03/08/2008 saat 19:14
kaynak kullanıcı
Diğer dillerde...                            


10 cevaplar

oy
17

Cramer Kuralı ve Gauss Eliminasyon iki iyi, genel amaçlı algoritmalar vardır (ayrıca bkz Eşzamanlı Lineer Denklemler ). Kod arıyorsanız, check out GiNaC , Maxima ve SymbolicC ++ (tabii lisans gereksinimlerine bağlı olarak).

DÜZENLEME: C topraklarda çalıştığını biliyorum, ama ben de iyi bir kelime koymak zorunda SymPy (Python bir bilgisayar cebir sistemi). (Eğer pitonun biraz okuyabilir ise) Bunu algoritmaları çok şey öğrenebilir. Ücretsiz matematik paketlerinin çoğu GPL iken Ayrıca, yeni BSD lisansı altında.

Cevap 03/08/2008 saat 19:37
kaynak kullanıcı

oy
15

Sen (o zaman denklem geri sonuçlarını besleyen, çarpma ve çıkarma ile birlikte) tam bir programla elle çözmek aynı şekilde bunu çözebiliriz. Bu oldukça standart ortaokul düzeyindeki matematik olduğunu.

-44.3940 = 50a + 37b + c (A)
-45.3049 = 43a + 39b + c (B)
-44.9594 = 52a + 41b + c (C)

(A-B): 0.9109 =  7a -  2b (D)
(B-C): 0.3455 = -9a -  2b (E)

(D-E): 1.2564 = 16a (F)

(F/16):  a = 0.078525 (G)

Feed G into D:
       0.9109 = 7a - 2b
    => 0.9109 = 0.549675 - 2b (substitute a)
    => 0.361225 = -2b (subtract 0.549675 from both sides)
    => -0.1806125 = b (divide both sides by -2) (H)

Feed H/G into A:
       -44.3940 = 50a + 37b + c
    => -44.3940 = 3.92625 - 6.6826625 + c (substitute a/b)
    => -41.6375875 = c (subtract 3.92625 - 6.6826625 from both sides)

Yani oluşturmuş oluruz:

a =   0.0785250
b =  -0.1806125
c = -41.6375875

geri A, B ve C içine bu değerleri fiş varsa, bunların doğru olduğunu göreceksiniz.

hile 3x2 matris "bir = N", N, gerçek sayı olmak veya daha sonra 2x1 sırayla azaltan basit bir 4x3 matris kullanmaktır. Ondan var sonra, başka değeri elde etmek kadar sonraki matris içine yem, o zaman bütün değişkenleri sonraki matris kadar içine bu iki değere çözdük kadar.

Eğer N farklı denklemler var kaydıyla, her zaman N değişkenleri için çözebilir. Bu iki değil, çünkü ben farklı ki:

 7a + 2b =  50
14a + 4b = 100

Bunlar aynı nedenle onlardan bir çözüm elde edemezsiniz iki ile çarpılır denklem - Doğru ama işe yaramaz deyimi ile iki sonra çıkarılarak yapraklar sizi ilk çarpılması:

0 = 0 + 0

Örnek olarak, burada senin soru yerleştirildikleri eşzamanlı denklemler dışarı çalışır bazı C kodu bulunuyor. İlk bazı gerekli tipleri, değişkenler, bir denklem basılmasına yarayan bir destek fonksiyonu ve başlangıç main:

#include <stdio.h>

typedef struct { double r, a, b, c; } tEquation;
tEquation equ1[] = {
    { -44.3940,  50, 37, 1 },      // -44.3940 = 50a + 37b + c (A)
    { -45.3049,  43, 39, 1 },      // -45.3049 = 43a + 39b + c (B)
    { -44.9594,  52, 41, 1 },      // -44.9594 = 52a + 41b + c (C)
};
tEquation equ2[2], equ3[1];

static void dumpEqu (char *desc, tEquation *e, char *post) {
    printf ("%10s: %12.8lf = %12.8lfa + %12.8lfb + %12.8lfc (%s)\n",
        desc, e->r, e->a, e->b, e->c, post);
}

int main (void) {
    double a, b, c;

Sonra, iki bilinmeyenli iki denklem için üç bilinmeyenli üç denklem azaltma:

    // First step, populate equ2 based on removing c from equ.

    dumpEqu (">", &(equ1[0]), "A");
    dumpEqu (">", &(equ1[1]), "B");
    dumpEqu (">", &(equ1[2]), "C");
    puts ("");

    // A - B
    equ2[0].r = equ1[0].r * equ1[1].c - equ1[1].r * equ1[0].c;
    equ2[0].a = equ1[0].a * equ1[1].c - equ1[1].a * equ1[0].c;
    equ2[0].b = equ1[0].b * equ1[1].c - equ1[1].b * equ1[0].c;
    equ2[0].c = 0;

    // B - C
    equ2[1].r = equ1[1].r * equ1[2].c - equ1[2].r * equ1[1].c;
    equ2[1].a = equ1[1].a * equ1[2].c - equ1[2].a * equ1[1].c;
    equ2[1].b = equ1[1].b * equ1[2].c - equ1[2].b * equ1[1].c;
    equ2[1].c = 0;

    dumpEqu ("A-B", &(equ2[0]), "D");
    dumpEqu ("B-C", &(equ2[1]), "E");
    puts ("");

Sonra, bir bilinmeyen ile bir denkleme iki bilinmeyenli iki denklem azaltma:

    // Next step, populate equ3 based on removing b from equ2.

    // D - E
    equ3[0].r = equ2[0].r * equ2[1].b - equ2[1].r * equ2[0].b;
    equ3[0].a = equ2[0].a * equ2[1].b - equ2[1].a * equ2[0].b;
    equ3[0].b = 0;
    equ3[0].c = 0;

    dumpEqu ("D-E", &(equ3[0]), "F");
    puts ("");

Şimdi türünde bir formüle sahip olduğunu number1 = unknown * number2, biz sadece bilinmeyen değeri çalışabilir unknown <- number1 / number2. Eğer dışarı bu değeri karar verdikten sonra, daha iki bilinmeyenli denklem birine yeğlemesini ve ikinci değer egzersiz yapın. Sonra orijinal denklem birine olanlar (şimdi bilinen) bilinmeyenler hem yerine ve artık her üç bilinmeyenli için değerleri vardır:

    // Finally, substitute values back into equations.

    a = equ3[0].r / equ3[0].a;
    printf ("From (F    ), a = %12.8lf (G)\n", a);

    b = (equ2[0].r - equ2[0].a * a) / equ2[0].b;
    printf ("From (D,G  ), b = %12.8lf (H)\n", b);

    c = (equ1[0].r - equ1[0].a * a - equ1[0].b * b) / equ1[0].c;
    printf ("From (A,G,H), c = %12.8lf (I)\n", c);

    return 0;
}

Bu kodun çıktısı bu yanıtında önceki hesaplamalar eşleşir:

         >: -44.39400000 =  50.00000000a +  37.00000000b +   1.00000000c (A)
         >: -45.30490000 =  43.00000000a +  39.00000000b +   1.00000000c (B)
         >: -44.95940000 =  52.00000000a +  41.00000000b +   1.00000000c (C)

       A-B:   0.91090000 =   7.00000000a +  -2.00000000b +   0.00000000c (D)
       B-C:  -0.34550000 =  -9.00000000a +  -2.00000000b +   0.00000000c (E)

       D-E:  -2.51280000 = -32.00000000a +   0.00000000b +   0.00000000c (F)

From (F    ), a =   0.07852500 (G)
From (D,G  ), b =  -0.18061250 (H)
From (A,G,H), c = -41.63758750 (I)
Cevap 26/02/2009 saat 11:59
kaynak kullanıcı

oy
7

lineer denklem bir 3x3 sistemi için ben kendi algoritmaları sunmaya iyi olacağını tahmin ediyorum.

Ancak, doğruluk, bölünme sıfır ya gerçekten küçük sayılarla ve ne sonsuz sayıda çözümler hakkında yapılacak dert gerekebilir. Benim önerim gibi standart bir sayısal lineer cebir paketi ile gitmektir LAPACK .

Cevap 08/08/2008 saat 18:59
kaynak kullanıcı

oy
6

Bir göz atın Microsoft Çözücü Vakfı .

Bununla beraber böyle bir kod yazabilirsiniz:

  SolverContext context = SolverContext.GetContext();
  Model model = context.CreateModel();

  Decision a = new Decision(Domain.Real, "a");
  Decision b = new Decision(Domain.Real, "b");
  Decision c = new Decision(Domain.Real, "c");
  model.AddDecisions(a,b,c);
  model.AddConstraint("eqA", -44.3940 == 50*a + 37*b + c);
  model.AddConstraint("eqB", -45.3049 == 43*a + 39*b + c);
  model.AddConstraint("eqC", -44.9594 == 52*a + 41*b + c);
  Solution solution = context.Solve();
  string results = solution.GetReport().ToString();
  Console.WriteLine(results); 

İşte çıktı şöyledir:
=== Çözücü Vakfı Hizmet Raporu ===
Datetime: 2009/04/20 23:29:55
Model Adı: Varsayılan
Özellikleri istendi: LP
1027: (ms) Zaman çözün
Toplam Süre (ms): 1414
çözün tamamlanma Durumu: Optimal
Çözücü Seçili: Microsoft.SolverFoundation.Solvers.SimplexSolver
Direktifleri:
Microsoft.SolverFoundation.Services.Directive
Algoritma: Primal
Aritmetik: Hibrid
Fiyatlandırma (tam): Varsayılan
Fiyatlandırma (çift): SteepestEdge
Esası: Slack
Pivot Sayısı: 3
== = Çözelti Ayrıntılar ===
Hedefleri:

kararlar:
a: ,0785250000000004
b: -,180612500000001
c: -41,6375875

Cevap 21/04/2009 saat 04:33
kaynak kullanıcı

oy
3

Şablon Sayısal Toolkit NIST bunu yaptığım için araçlara sahiptir.

Daha güvenilir yollarından biri kullanmaktır QR Decomposition .

Benim kodunda "GetInverse (A, INVA)" çağırabilir ve INVA içine ters koymak, böylece İşte bir sargının bir örnek.

void GetInverse(const Array2D<double>& A, Array2D<double>& invA)
   {
   QR<double> qr(A);  
   invA = qr.solve(I); 
   }

Array2D kütüphanesinde tanımlanır.

Cevap 25/08/2008 saat 19:53
kaynak kullanıcı

oy
3

Eğer çalışma yapacağız bir yazılım paketinin arayan veya fiilen matris operasyonları yapıyor ve bu tür ve her adımı mı?

İlk, benim bir iş arkadaşınız sadece kullanılan Ocaml GLPK . Sadece için bir sarıcı GLPK , ancak şeyler kurma adımları çok kaldırır. Bu da, C, GLPK sopa ile sahip olacak gibi görünüyor. İkincisinin için, eski bir makale kaydetmek için lezzetli sayesinde seni bir süre geri LP öğrenmek için kullanılan PDF . Eğer daha fazla kurma özel yardım gerekiyorsa, bize bildirin ve eminim, ben ya da geri dolaşmak ve yardımcı olabilir, ancak, bunun yalındır buradan oldukça düşünecek birisi. İyi şanslar!

Cevap 03/08/2008 saat 19:27
kaynak kullanıcı

oy
2

Değişkenler, ben gibi her zaman denklem aynı sayıda olacaksa çalışma zamanı verimliliği açısından, diğerleri daha iyi I. cevap vermiş Cramer kuralı o uygulamak kolaydır olarak. Sadece bir matrisin tersini hesaplamak için bir fonksiyon yazmak (ya da zaten yazmış birini kullanın Senin var bir tane bulabilirsiniz eminim) ve iki matrisin belirleyicilerini bölün.

Cevap 19/09/2008 saat 04:36
kaynak kullanıcı

oy
2

Eğer bilinmeyenler daha fazla denklemler varsa ve tutarsızlıkları en aza indirmek istiyorsanız gibi Sorunuzun ifadeler itibaren, öyle görünüyor. Bu tipik olarak, tutarsızlıklar karelerinin toplamını en aza indirecek lineer regresyon ile yapılır. Verilerin boyutuna bağlı olarak, bir e-tabloda veya istatistiksel bir pakette yapabilirsiniz. R diğer bir çok şey arasında, doğrusal regresyon yapan bir yüksek kaliteli, ücretsiz bir pakettir. Orada lineer regresyon (ve Yakaladım en çok) çok şey, ama basit durumlar için yapılacak basit olduğu gibi. İşte verileri kullanarak bir R örnek. "Tx" modelinize kesişme olduğunu unutmayın.

> y <- c(-44.394, -45.3049, -44.9594)
> a <- c(50.0, 43.0, 52.0)
> b <- c(37.0, 39.0, 41.0)
> regression = lm(y ~ a + b)
> regression

Call:
lm(formula = y ~ a + b)

Coefficients:
(Intercept)            a            b  
  -41.63759      0.07852     -0.18061  
Cevap 17/09/2008 saat 15:22
kaynak kullanıcı

oy
1
function x = LinSolve(A,y)
%
% Recursive Solution of Linear System Ax=y
% matlab equivalent: x = A\y 
% x = n x 1
% A = n x n
% y = n x 1
% Uses stack space extensively. Not efficient.
% C allows recursion, so convert it into C. 
% ----------------------------------------------
n=length(y);
x=zeros(n,1);
if(n>1)
    x(1:n-1,1) = LinSolve( A(1:n-1,1:n-1) - (A(1:n-1,n)*A(n,1:n-1))./A(n,n) , ...
                           y(1:n-1,1) - A(1:n-1,n).*(y(n,1)/A(n,n))); 
    x(n,1) = (y(n,1) - A(n,1:n-1)*x(1:n-1,1))./A(n,n); 
else
    x = y(1,1) / A(1,1);
end
Cevap 30/12/2014 saat 15:24
kaynak kullanıcı

oy
1

Şahsen ben bir algoritma kısmi değilim Sayısal Tarifler . (C ++ baskısının düşkün değilim.)

Bu kitap algoritmaları çalışmak neden öğretmek, ayrıca sana o algoritmaların bazıları oldukça-iyi ayıklanmış uygulamaları gösterecektir.

Tabii ki, sadece körü körüne kullanabilirsiniz CLAPACK bu algoritmaları verme gitti işin türden bir soluk fikir var (ben büyük bir başarı ile kullandım) ama önce en az bir Gauss Eliminasyon algoritmasını elle yazarsınız kararlı.

Eğer daha ilginç doğrusal cebir yapıyorsan Daha sonra, kaynak koduna etrafa Octave bir çok soru cevap verecektir.

Cevap 25/08/2008 saat 19:22
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more