Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6085
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Решение линейного уравнения
Мне нужно программно решить систему линейных уравнений в C, Objective C или (при необходимости) C++.
Вот пример уравнений:
-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
Исходя из этого, я хотел бы получить наилучшее приближение для a , b и tx .
Правило Крамера и Исключение Гаусса - это два хороших алгоритма общего назначения (см. Также одновременные линейные уравнения ). Если вы ищете код , проверьте GiNaC , Maxima и SymbolicC++ (в зависимости от ваших лицензионных требований, конечно).
EDIT: я знаю, что вы работаете в стране C, но я также должен замолвить словечко за SymPy (система компьютерной алгебры в Python). Вы можете многому научиться из его алгоритмов (если вы можете прочитать немного python). Кроме того, он находится под новой лицензией BSD, в то время как большинство бесплатных математических пакетов-это GPL.
Вы можете решить эту задачу с помощью программы точно так же, как вы решаете ее вручную (с умножением и вычитанием, а затем возвращаете результаты обратно в уравнения). Это довольно стандартная математика secondary-school-level.
-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)
Так что вы в конечном итоге с:
a = 0.0785250
b = -0.1806125
c = -41.6375875
Если вы вставите эти значения обратно в A, B и C, вы обнаружите, что они верны.
Хитрость состоит в том, чтобы использовать простую матрицу 4x3, которая в свою очередь сводится к матрице 3x2, а затем к матрице 2x1, которая является "a = n", n-фактическое число. Как только у вас это есть, вы вводите его в следующую матрицу, чтобы получить другое значение, а затем эти два значения в следующую матрицу, пока вы не решите все переменные.
Если у вас есть N различных уравнений, вы всегда можете решить для N переменных. Я говорю различное, потому что эти два не являются:
7a + 2b = 50
14a + 4b = 100
Они представляют собой одно и то же уравнение, умноженное на два, поэтому вы не можете получить из них решение - умножение первого на два, а затем вычитание оставляет вас с истинным, но бесполезным утверждением:
0 = 0 + 0
Например, вот некоторый код C, который работает с одновременными уравнениями, которые вы помещаете в свой вопрос. Сначала некоторые необходимые типы, переменные, вспомогательная функция для вывода уравнения и начало 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;
Далее следует сведение трех уравнений с тремя неизвестными к двум уравнениям с двумя неизвестными:
// 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 ("");
Далее следует сведение двух уравнений с двумя неизвестными к одному уравнению с одним неизвестным:
// 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 ("");
Теперь , когда у нас есть формула типа number1 = unknown * number2, мы можем просто вычислить неизвестное значение с помощью unknown <- number1 / number2 . Затем, как только вы вычислили это значение, подставьте его в одно из уравнений с двумя неизвестными и вычислите второе значение. Затем подставьте обе эти (теперь известные) неизвестные в одно из исходных уравнений, и теперь у вас есть значения для всех трех неизвестных:
// 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;
}
Выходные данные этого кода совпадают с предыдущими вычислениями в этом ответе:
>: -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)
Для системы линейных уравнений 3x3, я думаю, было бы неплохо развернуть свои собственные алгоритмы.
Однако вам, возможно, придется беспокоиться о точности, делении на ноль или действительно малые числа и о том, что делать с бесконечно большим количеством решений. Мое предложение состоит в том, чтобы пойти со стандартным пакетом численной линейной алгебры, таким как LAPACK .
Взгляните на Microsoft Solver Foundation .
С его помощью вы могли бы написать такой код:
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);
Вот такой выход:
===Решатель Фундамента Сервисной Отчета===
Datetime: 04/20/2009 23:29:55
Имя Модели: По Умолчанию
Запрошенные возможности: LP
Время решения (МС): 1027
Общее время (МС): 1414
Решить Статус Завершения: Оптимальный
Выбран Решатель: Microsoft.SolverFoundation.Solvers.SimplexSolver
Директивы:
Microsoft.SolverFoundation.Services.Directive
Алгоритм: Primal
Арифметика: Гибрид
Ценообразование (точное): по умолчанию
Цена (двойная): SteepestEdge
Основание: Провисание
Pivot количество: 3
= = = Детали Решения===
Цели:
Решения:
ответ: 0.0785250000000004
б: -0.180612500000001
c: -41.6375875
Вы ищете программный пакет, который будет выполнять эту работу или фактически выполнять операции с матрицей и тому подобное и выполнять каждый шаг?
Первый, мой коллега только что использовал Ocaml GLPK . Это всего лишь оболочка для GLPK,но она удаляет многие шаги настройки вещей. Хотя, похоже, вам придется придерживаться GLPK, в C году. Для последнего, благодаря delicious за сохранение старой статьи, которую я использовал, чтобы узнать LP некоторое время назад, PDF . Если вам понадобится конкретная помощь в дальнейшей настройке, дайте нам знать, и я уверен, что я или кто-то еще вернется и поможет, но я думаю, что это довольно прямолинейно отсюда. Удачи Вам!
Шаблон численного инструментария от NIST есть инструменты для этого.
Одним из наиболее надежных способов является использование QR-декомпозиции .
Вот пример обертки, чтобы я мог вызвать "GetInverse(A, InvA)" в своем коде, и он поместит обратное в InvA.
void GetInverse(const Array2D<double>& A, Array2D<double>& invA)
{
QR<double> qr(A);
invA = qr.solve(I);
}
Array2D определяется в библиотеке.
Судя по формулировке вашего вопроса, кажется, что у вас больше уравнений, чем неизвестных, и вы хотите свести к минимуму несоответствия. Обычно это делается с помощью линейной регрессии, которая минимизирует сумму квадратов несоответствий. В зависимости от размера данных, вы можете сделать это в электронной таблице или в статистическом пакете. R - это высококачественный, бесплатный пакет, который делает линейную регрессию, среди множества других вещей. В линейной регрессии есть много чего (и много готча), но как это просто сделать для простых случаев. Вот пример R с использованием ваших данных. Обратите внимание, что "tx"-это перехват вашей модели.
> 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
Если вы всегда будете иметь одинаковое количество уравнений в качестве переменных, то мне нравится правило Крамера , поскольку его легко реализовать. Просто напишите функцию для вычисления детерминанта матрицы (или используйте тот, который уже написан, я уверен, что вы можете найти его там) и разделите детерминанты двух матриц.
Лично я неравнодушен к алгоритмам численных рецептов . (Мне очень нравится издание C++.)
Эта книга научит вас, почему алгоритмы работают, а также покажет вам некоторые довольно хорошо отлаженные реализации этих алгоритмов.
Конечно, вы можете просто слепо использовать CLAPACK (я использовал его с большим успехом), но я бы сначала набрал алгоритм исключения Гаусса, чтобы иметь хотя бы слабое представление о том, какая работа была проделана для обеспечения стабильности этих алгоритмов.
Позже, если вы занимаетесь более интересной линейной алгеброй, просмотр исходного кода Octave ответит на множество вопросов.
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
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