Помощь - Поиск - Пользователи - Календарь
Полная версия: Уравнивани реакции.проблема с чтением данных
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Tribunal
Здравствуйте.
Мне нужно написать программу , которая будет уравнивать химическую реакцию.
Соответственно нужно прийти к СЛАУ, по которой и находить коэффициенты реакции.
В этом и состоит сейчас моя проблема.Написанный мною код в C++Builder 6 выдаёт ошибку о типе integer.
Вот собственно код.Надеюсь на какие-то идеи и вашу помощь.

На форме Edit'ы для введения элементов веществ и их индексов с расчетом на 3 вещества в левой части и 4- в правой.А так же-StringGrid для выведения полученной матрицы.

{

char *element[10][2];
int index[10][7];

//==x1==//
int x=0;
int i=0;
AnsiString a;

a=Edit1->Text;
*element[i]=Edit1->Text.c_str();
index[i][x]=StrToInt(Edit2->Text);


a=Edit3->Text;

for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=StrToInt(Edit4->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit4->Text);
};
}

a=Edit5->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=StrToInt(Edit6->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit6->Text);
};
}
//==x1==//

//==x2==//
x++;
a=Edit7->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=StrToInt(Edit8->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit8->Text);
};
}

a=Edit9->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=StrToInt(Edit10->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit10->Text);
};
}

a=Edit11->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=StrToInt(Edit12->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit12->Text);
};
}
//==x2==//

//==x3==//
x++;
a=Edit15->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=StrToInt(Edit16->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit16->Text);
};
}

a=Edit17->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=StrToInt(Edit18->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit18->Text);
};
}

a=Edit19->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=StrToInt(Edit20->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit20->Text);
};
}
//==x3==//

//==x4==//
x++;
a=Edit22->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit23->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit23->Text);
};
}

a=Edit24->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=-StrToInt(Edit25->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit25->Text);
};
}

a=Edit26->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit27->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit27->Text);
};
}
//==x4==//

//==x5==//
x++;
a=Edit28->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit29->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit29->Text);
};
}

a=Edit30->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=-StrToInt(Edit31->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit31->Text);
};
}

a=Edit32->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit33->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit33->Text);
};
}
//==x5==//

//==x6==//
x++;
a=Edit34->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit35->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit35->Text);
};
}

a=Edit36->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=-StrToInt(Edit37->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit37->Text);
};
}

a=Edit38->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit39->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit39->Text);
};
}
//==x6==//

//==x7==//
x++;
a=Edit40->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit41->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit41->Text);
};
}

a=Edit42->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{
index[j][x]=-StrToInt(Edit43->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit43->Text);
};
}

a=Edit44->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit45->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit45->Text);
};
}
//==x7==//

for (int i=0;i<10;i++)
{ for (int j=0;j<7;j++)
{ StringGrid1->Cells[j][i]=IntToStr(index[i][j]);
}
}
}
volvo
Цитата
Написанный мною код в C++Builder 6 выдаёт ошибку о типе integer
Можно уточнить, где именно он выдает ошибку? Строку в коде показать желательно... Кстати, ошибка этапа компиляции, или уже выполнения?

Потому как отследить что-то в программе, которая требует 45 Edit-ов просто нереально (от значения каждого из них может все кардинально измениться...)
Tribunal
строку указать не могу.
ошибка выдаётся,когда я нажимаю кнопку выполнения программы,то есть сам код компилируется без ошибок.
я думала,что дело в незаполненных полях..в принципе,так оно и есть...
но теперь,даже если заполнять все поля, всё равно вылазиет ошибка с указанием ее кода(код длинныйsmile.gif) и всё...вот.. (

прикрепляю файлы программы...
Нажмите для просмотра прикрепленного файла
volvo
Пример входных данных тогда уже тоже приведи... (лучше всего, введи данные, и сними скриншот, чтоб было видно о чем говорим).
Tribunal
вот пример входных данных
Нажмите для просмотра прикрепленного файла
при этом выдаёт ошибку к строке 96
Код
       index[i][x]=StrToInt(Edit12->Text);

%)
Tribunal
а...и подскажите,пожалуйста..
мне нужно найти коэффициенты к каждому веществу,т.е. нужно решить СЛАУ с правым нулевым столцом..
как лучшеэто сделать?
unsure.gif
volvo
Обрати внимание, что показывает CodeGuard:
Нажмите для просмотра прикрепленного файла

То есть, тебе надо обратить внимание на то, что у тебя при заданном размере массивов element и index происходит попытка работать с гораздо бОльшими индексами... Естественно, этого Builder не позволяет...
Tribunal
я сделала вот так(запоминание текущего размера массива элементов,т.е номер строки в двумерном массиве индексов),только выдаёт ошибку всё равно на 31 Edit'e (при тех же входных данных)... unsure.gif
for (int j=0;j<n;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=-StrToInt(Edit4->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=-StrToInt(Edit4->Text);
n=i;
};
}
volvo
Цитата
я сделала вот так
Это должно было что-то изменить? Ты что, теперь уверена, что при обращении по какому-то индексу ты не вылетаешь за пределы массива?
Tribunal
в описании массивов делать цифры больше тоже не помогает.тогда что?подскажите,пожалуйста...
volvo
У тебя немного неверна структура программы... Я не говорю о том, что можно все то, что ты написала в первом посте (с использованием FindComponent, например) уложить в 10 строк... Проблема в другом. Смотри:

Берем вот этот фрагмент:

Цитата
  a=Edit3->Text;
for (int j=0;j<10;j++)
{ if (a.c_str()==*element[j])
{ index[j][x]=StrToInt(Edit4->Text);
}
else
{ i++;
*element[i]=a.c_str();
index[i][x]=StrToInt(Edit4->Text);
};
}
Я так понимаю, что задумывалось следующее: пробежаться по всему массиву element, и если хоть один из *element[j] равен содержимому строки a, то добавить в соответствующую строку массива index значение, хранящееся в Edit4->Text. Если же ни один из элементов, хранящихся массиве element не содержит того же значения, что и a, то перейти на новую строку в массиве index. Так?

Код, который я процитировал, этого не делает... Вот так (насколько я понимаю задачу) будет правильно:

  a=Edit3->Text;
done = 0;
for (int j=0;j<10;j++)
if (a.c_str()==*element[j]) {
index[j][x]=StrToInt(Edit4->Text);
done = 1;
}
if(!done) { // Только если не нашли ничего в element
*element[++i]=a.c_str();
index[i][x]=StrToInt(Edit4->Text);
};

Tribunal
спасибо..
правда как-то странно всё это сейчас происходит..но я над этим работаю...))
а что за FindComponent в 10 строк? blink.gif

и кстати не подскажете алгоритм приведения матрицы к диагональному виду..?)
volvo
Цитата(Tribunal @ 7.11.2007 13:59) *
а что за FindComponent в 10 строк? blink.gif

Смотри, во что превратилась твоя процедура:

void __fastcall TForm1::Button1Click(TObject *Sender)
{

const int size = 21;
int numbers[size] = {
1, 3, 5, 7, 9, 11, 15, 17, 19,
22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44
};

AnsiString element[size];
int index[size][7] = {0};

int curr_line = 0;
for(int i = 0; i < size; ++i) {

TEdit *LetterEdit = (TEdit *)(Form1->FindComponent("Edit"+IntToStr(numbers[i])));
TEdit *IndexEdit = (TEdit *)(Form1->FindComponent("Edit"+IntToStr(numbers[i] + 1)));
AnsiString a = LetterEdit->Text;

bool found = false;
for(int j = 0; j < curr_line; ++j) {
if(element[j] == a) {
index[j][i / 3] = ((i > 8) ? -1 : 1) * StrToInt(IndexEdit->Text);
found = true; break;
}
}
if(!found) {
element[curr_line] = a;
index[curr_line++][i / 3] = ((i > 8) ? -1 : 1) * StrToInt(IndexEdit->Text);
}

}

for(int i = 0; i < curr_line; ++i) {
for(int j = 0; j < 7; j++) {
StringGrid1->Cells[j][i] = IntToStr(index[i][j]);
}
}
}

rolleyes.gif
Tribunal
ааа ужас какой lol.gif
классно!работает)) спасибо unsure.gif

извинитеза наглость,вы мне так уже очень помогли,
но всё-таки как лучше решить получившуюся СЛАУ.
есть смысл приводить к диагональному виду?
volvo
Я бы попробовал метод Холецкого: Решение систем (это в FAQ-е реализация на Паскале, перенести на С++ не должно быть проблемой)

Ну, или что-нибудь отсюда: AlgLib: Решение систем линейных уравнений
Tribunal
вот переделала код(метод Холецкого) под свою задачу.ругается на деление "/"...
посоветуйте, пожалуйста, что-нибудь?) может что-то еще нужно исправить?
посмотрите,пожалуйста...

Код
  int N=curr_line;
  int t,max,p,s;
  int b[21]={0};
  int x[21];

  for (int i=0;i<N;i++)
  { index[i][N]=b[i];}

  for (int i=0;i<N;i++)
  {

    int max=0;
    for (int j=0;j<N;j++)
    {
       if (max<abs(index[i][j]))
          {
             max=abs(index[i][j]);
             p=j;
          }
       }
       if (p!=i)
       {
        for (int j=0;j<N+1;j++)
        { index[N][j]=index[i][j];}
        for (int j=0;j<N+1;j++)
        { index[i][j]=index[p][j]; }
        for (int j=0;j<N+1;j++)
        { index[p][j]=index[N][j];}
       };
    }


    for (int j=0;j<N+1;j++)
    { index[0][j]=index[0][j]/index[0,0];}
    for (int m=0;m<N;m++)
    {
      for (int i=0;i<N;i++)
       {
        s=0;
        for (int k=0;k<m;k++)
        { s=s+index[i][k]*index[k][m];
          index[i][m]=index[i][m]-s;
        };
        for (int j=m+2;j<N+1;j++)
        {
          s=0;
          for (int k=0;k<m;k++)
          { s=s+index[m][k]*index[k][j];};
          index[m][j]=(index[m][j]-s)/index[m][m];
        };
    };
    x[N-1]=index[N-1][N];
    for (int i=N-2;i>=0;i--)
    {
      s=0;
      for (int k=i+1;k>N;k++)
      { s=s+index[i][k]*x[k];}
      x[i]=index[i][N]-s;
    }
   }



и еще вопрос небольшой.
может знаете как из формы1 проекта в билдере вызывать форму 2,
то етсь делать ее видимой...
объявление ее типа не помогает...не пойму как это сделать.. unsure.gif
volvo
Цитата
ругается на деление "/"...
Естественно... Ты хочешь int поделить на указатель? wink.gif

Вот так:
    for (int j=0;j<N+1;j++)
{ index[0][j]=index[0][j]/index[0][0];} // <--- внимательнее с индексами, это ДВУмерный массив
Tribunal
хмм странно теперь ругается на деление на ноль
в этой же строке, хотя в этом элементе массива совсем не ноль(
у меня теперь такие входные данные:
Нажмите для просмотра прикрепленного файла
volvo
Цитата
хотя в этом элементе массива совсем не ноль(
Это тебе кто сказал? Там БЫЛ не ноль, когда заполнялся StringGrid, но с тех пор много воды утекло:
Нажмите для просмотра прикрепленного файла

Сейчас там как раз 0 (проверялось на твоих исходных данных)
Tribunal
эээ...и что делать? unsure.gif
volvo
Скорее всего, твоя система имеет не единственное решение (или не имеет решения вообще), в таком случае надо смотреть в сторону вот этого метода, например: Поиск фундаментальной системы решений с минимизацией невязки
Tribunal
а если система имеет решение, но при этом нужно взять какую-то неизвестную свободной?
то есть установить значение,в зависимости от которого всё считается...
Tribunal
извините....пожалуйста! помогите сделать,чтобы этот код работал с моими матрицами...
у меня никак не получается=((
заранее спасибо!
Код
static const int maxsvditerations = 30;
double extsign(double a, double b);
double mymax(double a, double b);
double pythag(double a, double b);

void svdsolvefundamental([b]ap::real_2d_array a[/b],
     int m,
     int n,
    [b] ap::real_2d_array& solutions[/b],
     int& dimension)
{
    int nm;
    int minmn;

     ////........

    ap::real_1d_array rv1;
    ap::real_1d_array w;
    ap::real_2d_array v;
    bool flag;
    double epsilon;

    rv1.setbounds(1, n);
    w.setbounds(1, n);
    v.setbounds(1, n, 1, n);
    if( m<n )
    {
        minmn = m;
    }
    else
    {
        minmn = n;
    }
    g = 0.0;
    vscale = 0.0;
    anorm = 0.0;
    for(i = 1; i <= n; i++)
    {
        l = i+1;
        rv1(i) = vscale*g;
        g = 0;
        s = 0;
        vscale = 0;
        if( i<=m )
        {
            for(k = i; k <= m; k++)
            {
                vscale = vscale+fabs(a(k,i));
            }


      /// .....



    epsilon = epsilon*n*ap::machineepsilon;
    dimension = 0;
    for(i = 1; i <= n; i++)
    {
        if( fabs(w(i))<=epsilon )
        {
            dimension = dimension+1;
        }
    }
    solutions.setbounds(1, n, 0, dimension);
    for(i = 1; i <= n; i++)
    {
        solutions(i,0) = 0;
        for(j = 1; j <= m; j++)
        {
            solutions(i,0) = solutions(i,0)+a(j,i)*a(j,n+1);
        }
    }
    k = 1;
    for(j = 1; j <= n; j++)
    {
        if( fabs(w(j))>epsilon )
        {
            for(i = 1; i <= n; i++)
            {
                v(i,j) = v(i,j)/w(j);
            }
        }
        else
        {
            for(i = 1; i <= n; i++)
            {
                solutions(i,k) = v(i,j);
            }
            k = k+1;
        }
    }
    for(i = 1; i <= n; i++)
    {
        a(1,i) = 0;
        for(j = 1; j <= n; j++)
        {
            if( fabs(w(j))>epsilon )
            {
                a(1,i) = a(1,i)+v(i,j)*solutions(j,0);
            }
        }
    }
    for(i = 1; i <= n; i++)
    {
        solutions(i,0) = a(1,i);
    }
}


вот файлы этого алгоритма
Нажмите для просмотра прикрепленного файла
Нажмите для просмотра прикрепленного файла
volvo
По-моему, было бы проще добавить в код пару строк, конвертирующих массив index в объект типа ap::real_2d_array. Если брать за основу то, что я привел в посте №13, то достаточно добавить после заполнения StringGrid-а вот это:

  ap::real_2d_array arr;
arr.setbounds(1, curr_line, 1, 8);
for (int i = 1; i <= curr_line; i++) {
for(int j = 1; j <= 7; j++) {
arr(i, j) = index[i - 1][j - 1];
}
arr(i, 8) = 0;
}
int dimension;
ap::real_2d_array solution;
svdsolvefundamental(arr, curr_line, 7, solution, dimension);
Memo1->Lines->Add("Solution:");
for(int j = 1; j <= 7; j++)
Memo1->Lines->Add(FloatToStr(solution(j, 0)));

, и в мемо будет записано частное решение системы. Ну, и базис выводится аналогично...

Только все-же что-то с системой не так... Получается нулевое решение, хотя тестовые примеры показывают работоспособность svdsolvefundamental...
-Tribunal-
вот например для уравнивания
KMnO_4+KNO_2+H_2SO_4-->MnSO_4+KNO_3+K_2SO_4+H_2O
при нахождении коэффициентов из линейных уравнений,
нужно положить одному из коэфф-тов значение.
может использовать ненулевую правую часть?
не знаю что делать=((

p.s. ответить со своего аккаунта не могу.ошибка в форуме.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.