Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как это сделать на С? 
:(
    Опции темы
spea
Дата 22.10.2012, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



С помощью чего и как лучше реализовать эту задачу на языке С?
Попробую кратко описать задачу. Имеются данные в txt файле в следующем виде:
23.020834 56.979168 -9.01
23.062500  56.979168  -10.37
23.104166  56.979168  -11.98
23.145834  56.979168  -13.84
23.187500  56.979168  -15.44
23.229166  56.979168  -17.79
23.312500  56.979168  -18.47
23.354166  56.979168  -19.25
23.395834  56.979168  -20.15

Количество строк заранее не известно, их около 30 000. В каждой строке 3 характеристики (A, B, C) одной точки.  Точки можно условно пронумеровать от 1 до k.
В общем, для каждой точки нужно рассчитать ещё одно значение (D). 
Для i-ой точки Di= сумма произведений Ck* (Ak - Ai) * (Bk - Bi).
Так например 
для первой точки D1 =  C1 * (A1 - A1) * (B1 - B1) + C2 * (A2 - A1) * (B2 - B1) + ... + Ck * (Ak - A1) * (Bk - B1)

для второй точки D2 =  C1 * (A1 - A2) * (B1 - B2) + C2 * (A2 - A2) * (B2 - B2) + ... + Ck * (Ak - A2) * (Bk - B2)

и т.д. для всех точек k.

Основная мысль в том, что сначала исходные данные нужно считать в массив, затем проиндексировать и составить алгоритм расчета D. Но вместо всего столбца удается считать только первое значение. 
И ещё не понятно как быть, если исходные данные разбиты на 2 файла.

Это сообщение отредактировал(а) spea - 23.10.2012, 00:07
PM MAIL   Вверх
feodorv
Дата 22.10.2012, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(spea @  22.10.2012,  21:18 Найти цитируемый пост)
Количество строк заранее 

В принципе, можно открыть файл и посчитать количество строк:
Код

FILE *stream = fopen( "data.txt", "r");
char line[256];
int N = 0;

if( stream == NULL )
{
  printf( "Can't open input file\n" );
  exit( -1 );
}

while( fgets( line, sizeof(line), stream) != NULL ) N++;


Тогда заранее будет известен размер требуемого массива. Далее запрашивается память нужного размера:
Код

double *a, *b, *c, *d;

a = (double *) malloc( N * sizeof(double) );
b = (double *) malloc( N * sizeof(double) );
c = (double *) malloc( N * sizeof(double) );
d = (double *) malloc( N * sizeof(double) );

if( a == NULL || b == NULL || c == NULL || d == NULL )
{
  printf( "No more free memory\n" );
  exit( -1 );
}

(можно и через calloc).

Далее читаем файл данных (с самого начала) построчно:
Код

int index = 0;

fseek( stream, 0, SEEK_SET);
while( fgets( line, sizeof(line), stream) != NULL )
{
   if( index >= N )
   {
      printf( "Internal error\n" );
      exit( -1 );
   }

   if( sscanf( line, "%lf %lf %lf", &a[index], &b[index], &c[index]) == 3 ) 
     index++;
  else
     printf( "Invalid string format: %s", line);
}

fclose( stream );

N = index; // <- число считанных точек
if( N == 0 )
{
  printf( "Error: no data\n" );
  exit( -1 );
}


Далее высчитываем значения массива d.


Цитата(spea @  22.10.2012,  21:18 Найти цитируемый пост)
сначала исходные данные нужно считать в массив

Уже считали, только не в один массив, а в три - a, b, c. При желании, можно структуру использовать вида:
Код
struct point
{
  double a, b, c;
};

И работать уже с массивом структур, но это не принципиально.


Цитата(spea @  22.10.2012,  21:18 Найти цитируемый пост)
затем проиндексировать

Что имеется в виду? 


Цитата(spea @  22.10.2012,  21:18 Найти цитируемый пост)
Но вместо всего столбца удается считать только первое значение.

Код приведите, пожалуйста)))

Добавлено через 8 минут и 47 секунд
Цитата(spea @  22.10.2012,  21:18 Найти цитируемый пост)
И ещё не понятно как быть, если исходные данные разбиты на 2 файла. 

Можно объединить два файла в один. А можно сконструировать так программу, чтобы она работала с несколькими файлами.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
spea
Дата 23.10.2012, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



Спасибо большое за помощь! 

Цитата
Цитата
Но вместо всего столбца удается считать только первое значение.
Код приведите, пожалуйста)))
Затупил) выводил в файл только первый элемент массива по типу 
Код

fprintf(wr, "%lf %lf %lf", a[0], b[0], c[0]);
 
Цитата
Цитата
затем проиндексировать
Что имеется в виду?

Каким то образом присвоить индексы i и k из форумы. В начале пытался сделать на основе куска этого кода
Код
for(i=1;i<=kt;i++)      {fscanf(fp,"%d%lf%lf%f%f",&K,&B1,&L1,&H1,&dg0);
    nom[i]=K;
    B[K]=B1;
    L[K]=L1;
    H[K]=H1;
    dg[K]=dg0;
Код

//sprintf(buf,"%d",K);
/*Определение xi0*/
   for (i=1;i<=kt;i++)
 {SUM=0;
  for(j=1;j<=kt;j++)
 {if (nom[i]!=nom[j])
 {i1=nom[i];
  j1=nom[j];
Но мне посоветовали, что лучше начать с нуля. И, в общем, я плохо представляю как реализовать ту формулу. 

И вопрос ещё по файлам. В конечном итоге их должно быть около 300. Лучше их объединять, так?

P.S. Извиняюсь, что наверно большая половина, написанного мной, похоже на бред)

Это сообщение отредактировал(а) spea - 23.10.2012, 00:05
PM MAIL   Вверх
feodorv
Дата 23.10.2012, 01:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(spea @  23.10.2012,  01:05 Найти цитируемый пост)
Извиняюсь, что наверно большая половина, написанного мной, похоже на бред)

Ничего, попробуем разобраться  smile 


Цитата(spea @  23.10.2012,  01:05 Найти цитируемый пост)
Каким то образом присвоить индексы i и k из форумы.

Вот это в каком смысле? Ясно же сказано: 
Цитата
сумма произведений
. Вот и нужно суммировать произведения:
Код
int i, k;

d[i] = 0;
for( k = 0; k < N; k++) d[i] += c[k] * (a[k] - a[i]) * (b[k] - b[i]);
 Формула - один в один с заданием, даже представить себе не могу возникшего затруднения...


Цитата(spea @  23.10.2012,  01:05 Найти цитируемый пост)
В конечном итоге их должно быть около 300

Эти данные - независимы друг от друга (для каждого файла - свои N и d), или все их нужно объединить в одну общую большую кучу?


PS Какая у Вас операционка?


Цитата(spea @  23.10.2012,  01:05 Найти цитируемый пост)
"%d%lf%lf%f%f"

Вот это всё есть в файле, или же файл всё-таки такого формата:
Цитата(spea @  22.10.2012,  21:18 Найти цитируемый пост)
23.020834 56.979168 -9.01
23.062500  56.979168  -10.37
23.104166  56.979168  -11.98
23.145834  56.979168  -13.84
23.187500  56.979168  -15.44
23.229166  56.979168  -17.79
23.312500  56.979168  -18.47
23.354166  56.979168  -19.25
23.395834  56.979168  -20.15

Тогда откуда там аж 5 значений на строчку???

Цитата(spea @  23.10.2012,  01:05 Найти цитируемый пост)
fprintf(wr, "%lf %lf %lf", a[0], b[0], c[0]);

Нет, всё-таки три... А разделитель строк '\n' Вы запихиваете в файл? Почему тогда не так:
Код

fprintf(wr, "%lf %lf %lf\n", a[i], b[i], c[i]);



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
spea
Дата 23.10.2012, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



Цитата
Формула - один в один с заданием, даже представить себе не могу возникшего затруднения...
 Мда, оказалось всё гораздо проще) а я думал, что k нужно присваивать аналогично i, и цикл for делать для двух переменных i и k  ) Похоже исходная программа только запутала меня. 
Цитата
Нет, всё-таки три... А разделитель строк '\n' Вы запихиваете в файл?
Для проверки того, что считалось в массив, теперь записываю так:
Код
      for(index=0;index<N;++index)
      {
          fprintf(wr,"%f %f %.2f\n",a[index], b[index], c[index] );
      }
Цитата
PS Какая у Вас операционка?
 В смысле память? 2 Gb. Если ось, то Windows.

Цитата
Эти данные - независимы друг от друга (для каждого файла - свои N и d), или все их нужно объединить в одну общую большую кучу?
 Это одна большая куча данных, скорее всего их нужно "сшивать".

Сама исходная задача звучит несколько иначе: идет интегрирование по поверхности сферы, и двойной интеграл заменяется суммой. А первые две (А, B) координаты в строке это широта и долгота. Поэтому все данные взаимосвязаны, по примерным подсчетам около 40 млн точек. И D считается несколько сложнее, а здесь попытался отразить только то, что вызвало вопросы. 
Для меня это вводная задача и в тему исследования и, вообще, в программирование.

И ещё кое-что. Предполагаю, что в дальнейшем мне придется выполнять задачи такого типа: решение дифференциальных и интегральных уравнений с краевыми условиями, преобразование Фурье и др. Слышал о подключении библиотек Matlab или Scilab. Можете ли порекомендовать литературу, где описывается как реализовать такое в С?

feodorv, ещё раз спасибо, Вы мне невероятно помогли. 


Это сообщение отредактировал(а) spea - 23.10.2012, 09:44
PM MAIL   Вверх
feodorv
Дата 23.10.2012, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(spea @  23.10.2012,  10:32 Найти цитируемый пост)
Можете ли порекомендовать литературу, где описывается как реализовать такое в С?

Увы, нет. Лучше всего задать этот вопрос в отдельной теме smile 


Цитата(spea @  23.10.2012,  10:32 Найти цитируемый пост)
цикл for делать для двух переменных i и k  )

Цитата(spea @  23.10.2012,  10:32 Найти цитируемый пост)
двойной интеграл заменяется суммой

Двойной интеграл - двойная сумма. Может, где-то нужен цикл и по i, проверьте, пожалуйста. Но d[i] вычисляется именно так.


Цитата(spea @  23.10.2012,  10:32 Найти цитируемый пост)
40 млн точек

Это много.... Таких массивов ОС может не создать...


Цитата(spea @  23.10.2012,  10:32 Найти цитируемый пост)
         fprintf(wr,"%f %f %.2f\n",a[index], b[index], c[index] );

 smile

Добавлено через 12 минут и 3 секунды
Цитата(feodorv @  23.10.2012,  18:24 Найти цитируемый пост)
Таких массивов ОС может не создать...

Нет, ничего, создаёт:
Код
#include <stdio.h>

int main( void )
{
  double *a, *b, *c, *d;
  int N = 40000000;

  a = (double *) malloc( N * sizeof(double) );
  printf( "a is %p\n", a);

  b = (double *) malloc( N * sizeof(double) );
  printf( "b is %p\n", b);

  c = (double *) malloc( N * sizeof(double) );
  printf( "c is %p\n", c);

  d = (double *) malloc( N * sizeof(double) );
  printf( "d is %p\n", d);
}


Цитата

a is 00510020
b is 13640020
c is 26770020
d is 398A0020



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
spea
Дата 24.10.2012, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



В первом приближении получилось следующее
Скрытый текст
Код
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>

#define R 6371000 /* средний радиус */ 
#define b 6357000 /* малая полуось */
#define ng 980.6 /* нормальная сила тяжести */
#define pi 3.141592654 /* пи */
#define h 0.041666667 /* шаг сетки в рад */

int main( void )
{
      FILE *f = fopen( "d:\\f.txt", "r"); /* файл с исходными данными  */ 
      FILE *wr = fopen( "d:\\w.txt", "w"); /* файл для записи  */
      char line[256];
      int N = 0;
      
      if( f == NULL )
      {
      printf( "Can't open input file\n" );
      exit( -1 );
      }
      
      while( fgets( line, sizeof(line), f) != NULL ) 
      N++; /* подсчет количества строк */
     
      double *lon, *lat, *faa; /* широта, долгота, аномалия силы тяжести */ 
      
      lon = (double *) malloc( N * sizeof(double) );
      lat = (double *) malloc( N * sizeof(double) );
      faa = (double *) malloc( N * sizeof(double) ); /* запрос памяти нужного размера  */

      if( lon == NULL || lat == NULL || faa == NULL )
      {
      printf( "No more free memory\n" );
      exit( -1 );
      }
      
      int i = 0;
      fseek( f, 0, SEEK_SET);
      
      while( fgets( line, sizeof(line), f) != NULL ) /* считывание данных построчно */
      {
        if( i >= N )
          {
          printf( "Internal error\n" );
          exit( -1 );
          }
        if( sscanf( line, "%lf %lf %lf", &lon[i], &lat[i], &faa[i]) == 3 ) 
        i++; 
        else
        printf( "Invalid string format: %s", line);
      }
               
      N = i; /* число считанных точек  */
      
      if( N == 0 )
      {
          printf( "Error: no data\n" );
          exit( -1 );
      }
      
      for( i=0; i < N; ++i) /* перевод градусы в радианы  */
      {
          lon[i] = lon[i]*pi/180;
          lat[i] = lat[i]*pi/180;
      }
      
      int k = N;
      
      double p[i][k]; /* сферическое расстояние  */      
      for( i = 0; i < N; i++)
      { 
          for( k=0; k < N; k++)
          {
               p[i][k] = acos((sin(lon[i])*sin(lon[k])+
               cos(lon[i])*cos(lon[k])*cos(lat[k]-lat[i])));
          }
      }     
      
      double FS[i][k]; /* функция стокса  */
      double Z = 0; 
      for( i = 0; i < N; i++)
      {
          for( k = 0; k < N; k++)
          {
          if ( i == k ) FS[i][k] == 0; /* исключение ошибок деления на 0  */
          else
          {   
               Z = p[i][k];
               FS[i][k] = (1/sin(Z/2) - 6*sin(Z/2) + 1 - 5*cos(Z) - 
               3*cos(Z)*log(sin(Z/2) + pow(sin(Z/2),2)));
          }
          }
      } 
                   
      double A[i]; /* площадь ячейки */
      for( i=0; i < N; i++)
      {
           A[i]= fabs(pow(b,2)*h*(sin(lon[i]+h/2)-sin(lon[i]-h/2)));
      }

      double G[i]; /* расчет аномалии высоты в каждой точке */
      for( i = 0; i < N; i++)
      { 
          for( k = 0; k < N; k++)   
          {
          G[i]+= (A[i]*faa[i]*FS[i][k])/(4*1000*pi*ng*R);
          }
      }
                     
      for( i = 0; i < N; i++) /* записать расчеты в файл  */
      {
           fprintf(wr,"%lf %lf %lf\n", lon[i], lat[i], G[i] );
      }
      
      fclose( f );
      fclose( wr );
}


Появилось несколько вопросов.
Первый: 
для всех массивов нужно выделять память по типу (double *) malloc( N * sizeof(double) ), а для двухмерного (double **) malloc( N * sizeof(double *) ) ? и когда необходимо производить освобождение памяти?

Второй: 
FS[i][k] вычисляется по значению аркосинуса. А для ячеек типа [1][1] или [5][5], т.е когда i равно k, аркосинус равен 0, из-за чего происходит деление на 0. То что у меня записано как  if ( i == k ) FS[i][k] == 0;  не всегда срабатывает: часть значений обращается в ноль, другие - в минус ноль, третьи - занимают пол экрана. В общем, как можно исключить эти значения?

Третий:
При обработке большого числа точек (около 500) программа выкидывает ошибку. Понимаю, что вычисление реализованы хуже некуда, а попытками улучшить делаю только хуже. Что именно необходимо исправить в программе, чтобы оптимизировать её работу ?
PM MAIL   Вверх
feodorv
Дата 24.10.2012, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Гм. Вы понимаете, что линейные массивы требуют памяти размером N*sizeof(double) байт, а двумерные - уже N*N*sizeof(double), что для 500 элементов увеличивает размер требуемой памяти в 500 раз? Судя по коду, можно обойтись только линейными массивами, вычисляя p[i][k] и FS[i][k] по ходу цикла по переменной i.


Цитата(spea @  24.10.2012,  19:36 Найти цитируемый пост)
При обработке большого числа точек (около 500) программа выкидывает ошибку. 

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


Цитата(spea @  24.10.2012,  19:36 Найти цитируемый пост)
для всех массивов нужно выделять память по типу (double *) malloc( N * sizeof(double) ), а для двухмерного (double **) malloc( N * sizeof(double *) ) ?

И не только:
Код
double **p = (double **) malloc( N * sizeof(double *) ); // <- проверить, что не NULL
for( i = 0; i < N; i++) p[i] = (double *) malloc( N * sizeof(double) ); // <- проверить, что не NULL



Цитата(spea @  24.10.2012,  19:36 Найти цитируемый пост)
и когда необходимо производить освобождение памяти?

В момент, когда память больше не нужна. Но по окончанию процесса память высвобождается автоматически, поэтому если выделенная память нужна до самого конца, то можно её вообще не высвобождать)))


Цитата(spea @  24.10.2012,  19:36 Найти цитируемый пост)
FS[i][k] вычисляется по значению аркосинуса. А для ячеек типа [1][1] или [5][5], т.е когда i равно k, аркосинус равен 0, из-за чего происходит деление на 0. То что у меня записано как  if ( i == k ) FS[i][k] == 0;  не всегда срабатывает: часть значений обращается в ноль, другие - в минус ноль, третьи - занимают пол экрана. В общем, как можно исключить эти значения?

Не увидел деления на FS[i][k]... Умножение - да, видел...

Если действительно в интегральной формуле знаменатель обращается в 0, значит и числитель тоже, и здесь нужно пользоваться разложением вблизи нуля (типа sin(x)/x ~= 1 - x*x/6 + ...)



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
spea
Дата 24.10.2012, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



Цитата

Не увидел деления на FS[i][k]... Умножение - да, видел...
Само FS[i][k] вычисляется вычисляется по формуле, где получатся деление на 0. 

FS[i][k] = 1/sin(Z/2) - 6*sin(Z/2) + 1 - 5*cos(Z) -  3*cos(Z)*log(sin(Z/2) + pow(sin(Z/2), 2));

так вот когда Z = 0, а Z равен нулю в точках i = k, происходит деление на ноль, а ещё нахождение натурального логарифма нуля, и в память заносится значение 1.#INF00 . 
Не понятно как заставить программу в этих точках игнорировать это значение или давать значение FS[i][k], при i = k, равное нулю.
PM MAIL   Вверх
feodorv
Дата 24.10.2012, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Аааа))) Опять же, FS[i][k] не существует сам по себе, оно потом умножается на что-то близкое к 0.
Цитата(feodorv @  24.10.2012,  21:04 Найти цитируемый пост)
здесь нужно пользоваться разложением вблизи нуля (типа sin(x)/x ~= 1 - x*x/6 + ...)




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 25.10.2012, 00:33 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(spea @  24.10.2012,  18:36 Найти цитируемый пост)
 if ( i == k ) FS[i][k] == 0;  не всегда срабатывает: 

мягко сказано. Оно вообще никогда не сработает.
лишний "=" уберите.


PM MAIL   Вверх
spea
Дата 25.10.2012, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



Цитата
лишний "=" уберите.
Понятно, почему вдруг программа начала правильно считать. Вчера сам случайно удалил его) Теперь в плане математики ошибок нет. Проверял для небольшого числа точек в Excel.

Выкладываю вторую версию кода. Просьба посмотреть на наличие ошибок и указать на то, что можно сделать лучше и эффективнее.

Скрытый текст
Код
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>

#define R 6371302 /* средний радиус */
#define b 6356752 /* малая полуось */
#define ng 980.6 /* гамма нулевое */
#define pi 3.141592654 /* пи */
#define h 0.000727221 /* шаг сетки в рад */

int main( void )
{
      FILE *f = fopen( "d:\\f.txt", "r"); /* файл с исходными данными */ 
      FILE *wr = fopen( "d:\\w.txt", "w"); /* файл для записи */
      char line[256];
      int N = 0;
      
      if( f == NULL )
      {
            printf( "Can't open input file\n" );
            exit( -1 );
      }

      while( fgets( line, sizeof(line), f) != NULL ) 
      N++; /* подсчет количества строк */
     
      float *lon, *lat, *faa; /* широта, долгота, аномалия FA */
      lon = (float *) malloc( N * sizeof(float) );
      lat = (float *) malloc( N * sizeof(float) );
      faa = (float *) malloc( N * sizeof(float) ); /* запрос памяти */ 
      if( lon == NULL || lat == NULL || faa == NULL )
      {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
      }
      
      int i = 0;
      fseek( f, 0, SEEK_SET);

      while( fgets( line, sizeof(line), f) != NULL ) /* считывание данных */ 
      {
          if( i >= N )
          {
              printf( "Internal error\n" );
              getch( );
              exit( -1 );
          }
          if( sscanf( line, "%f %f %f", &lon[i], &lat[i], &faa[i]) == 3 ) 
          i++; 
          else
          printf( "Invalid string format: %s", line);
      }
               
      N = i; /* число считанных точек */
      
      if( N == 0 )
      {
          printf( "Error: no data\n" );
          exit( -1 );
      }
      
      for( i=0; i < N; ++i) /* перевод градусы в радианы */
      {
          lon[i] = lon[i]*pi/180;
          lat[i] = lat[i]*pi/180;
      }
      
      int k = N;
   
      float **p = (float **) malloc( N * sizeof(float *) ); /* сферическое расстояние */
      if( p == NULL )
      {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
      }  
      
      for( i = 0; i < N; i++) /* запрос памяти */ 
      { 
           p[i] = (float *) malloc( N * sizeof(float) );
           if( p[i] == NULL )
           {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
           }
      }       

      for( i = 0; i < N; i++) /* расчет сферического расстояния */
      { 
          for( k=0; k < N; k++)
          {
               p[i][k] = acos((sin(lon[i])*sin(lon[k])+
               cos(lon[i])*cos(lon[k])*cos(lat[k]-lat[i])));
          }
      }     
      
      float **FS = (float **) malloc( N * sizeof(float *) ); /* функция стокса */
      if( FS == NULL )
      {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
      }  
      
      for( i = 0; i < N; i++) /* запрос памяти */ 
      { 
           FS[i] = (float *) malloc( N * sizeof(float) );
           if( FS[i] == NULL )
           {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
           }
      }   
      
      for( i = 0; i < N; i++) /* расчет функции стокса */
      {
          for( k = 0; k < N; k++)
          {
                if (i == k) FS[i][k] = 0; /* исключение ошибок /0 и ln(0) */
                else
                {
                FS[i][k] = (1/sin(p[i][k]/2) - 6*sin(p[i][k]/2) + 1 - 5*cos(p[i][k]) - 
                3*cos(p[i][k])*log(sin(p[i][k]/2) + pow(sin(p[i][k]/2),2)));
                }
          }
      }
            
      for ( i = 0; i < N; i++ ) /* освобождение памяти */ 
      free( p[i] );
      free( p ); 
      
      float *A; /* площадь ячейки */
      A = (float *) malloc( N * sizeof(float) ); /* запрос памяти */
      if( A == NULL )
      {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
      }        

      for( i=0; i < N; i++) /* расчет площади ячейки */
      {
           A[i] = fabs(pow(b,2)*h*(sin(lon[i]+h/2)-sin(lon[i]-h/2)));
      }  
      
      free( lat ); /* освобождение памяти */ 
      free( lon );   
     
      float *G; /* аномалия высоты */
      G = (float *) malloc( N * sizeof(float) );
      if( G == NULL )
      {
           printf( "No more free memory\n" );
           getch( );
           exit( -1 );
      } 
       
      for( i = 0; i < N; i++) /* расчет аномалии высоты */
      { 
           G[i] = 0;
           for( k = 0; k < N; k++)
           {
               G[i] += (A[i]*faa[i]*FS[i][k])/(4*1000*pi*ng*R);
           }
      }
      
      for ( i = 0; i < N; i++ ) /* освобождение памяти */ 
      free( FS[i] ); 
      free( FS );
      free( A ); 
      free( faa );
              
      for( i = 0; i < N; i++) /* записать данные в файл */
      { 
          fprintf(wr, "G [%d] = %f \n", i+1,  G[i] );  
      }
      
      getch( );
      free( G );
      fclose( f );
      fclose( wr ); /* закрыть файлы */
}




Это сообщение отредактировал(а) spea - 25.10.2012, 21:26
PM MAIL   Вверх
feodorv
Дата 25.10.2012, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(spea @  25.10.2012,  21:18 Найти цитируемый пост)
Не могу понять: проблема в коде или просто не хватает оперативной памяти? 

И то, и другое)))

Цитата(feodorv @  24.10.2012,  21:04 Найти цитируемый пост)
// <- проверить, что не NULL

А этой проверки не сделано. При нехватке памяти (а её и не может хватить на 20000 * 20000  double элементов), malloc возвращает NULL, по которому адресу Вы и пытаетесь обратиться.

Алгоритм необходимо переписать под использование только линейных массивов, но никак не двумерных...

Это сообщение отредактировал(а) feodorv - 25.10.2012, 20:27


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
spea
Дата 25.10.2012, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 22.10.2012

Репутация: нет
Всего: нет



Цитата
// <- проверить, что не NULL
 Спасибо, наконец то с этим разобрался. Теперь программа сразу сообщает "No more free memory", если данных слишком много. 

Цитата
Алгоритм необходимо переписать под использование только линейных массивов, но никак не двумерных...

Посмотрю, что можно сделать, но боюсь, что это маловероятно. 

Скорее всего надо преобразовывать исходные данные, чтобы не обрабатывать 40 млн точек.

PM MAIL   Вверх
feodorv
Дата 25.10.2012, 23:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(spea @  25.10.2012,  22:18 Найти цитируемый пост)
но боюсь, что это маловероятно. 

Посмотрите хотя бы на массивы FS[ i ][ k ], p[ i ][ k ] и то, как они используется. Их вполне можно заменить на вызовы функций
Код

float p( int i, int k, float *lon, float *lat)
{
   return acos( sin(lon[ i ]) * sin(lon[ k ]) + cos(lon[ i ]) * cos(lon[ k ]) * cos(lat[ k ]-lat[ i ]) );
}

float F( int i, int k, float *lon, float *lat)
{
  if( i == k ) return 0; /* исключение ошибок /0 и ln(0) */

  float pik = p( i, k, lon, lat);
  return 1./sin(pik/2.) - 6.*sin(pik/2.) + 1. - 5.*cos(pik) - 
                3.*cos(pik)*log(sin(pik/2.) + pow(sin(pik/2.),2.));
}

Вот что здесь маловероятного?

А если ещё и массивы lon и lat сделать глобальными, то не нужно будет их передавать в качестве аргументов... Хотя и так хорошо)))

Это сообщение отредактировал(а) feodorv - 26.10.2012, 04:29


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1098 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.