Форум программистов, компьютерный форум CyberForum.ru

Расчёт дисперсии - C++

Восстановить пароль Регистрация
 
GTG
0 / 0 / 0
Регистрация: 10.03.2013
Сообщений: 7
25.04.2013, 08:28     Расчёт дисперсии #1
Привет!
У меня возникла странная проблема - при считывании столбца данных из текстового файла (данных около 20 000) и расчёта дисперсии - она получается равной нулю (если считываю именно из второго столбца!). Если же считываю из первого, то, вроде, все нормально. В первом столбце числа порядка 0.04, во втором - порядка 7.0.
Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    for (int i=0; i<10000; i++) {
                fscanf(f, "%lf  %lf %lf", &a, &w0[i], &c);
                //printf("%g\n", w0[i]);
                //s1 = s1 + w0[i];
                a1 = a1 + w0[i]*w0[i];
                a2 = a2 + w0[i];
            }   
            //printf("s1 = %lf\n", s1/20000);
            //printf("d1 = %lf\n", a1/20000);
            wf[0] = w0[0];
            p[0] = 0;
            for (int i=1; i<10000; i++) {
                    p[i] = (1 - (p[(i-1)]/((p[(i-1)]+r)))) * p[(i-1)] + q;
                    wf[i] = (1 - (p[(i-1)]/((p[(i-1)]+r)))) * wf[(i-1)] + p[(i-1)]*w0[i]/((p[(i-1)]+r));
                    //printf("%g\n", wf[i]);
                    //s = s + wf[i];    
                    b1 = b1 + wf[i]*wf[i];
                    b2 = b2 + wf[i];
                }
            //printf("s = %lf\n", s/20000);
            //printf("d1 = %lf\n", d/20000);
            d1 = a1/10000 - (((a2*a2)/10000)/10000);
            printf("d1 = %lf\n", d1);
            d = b1/10000 - (((b2*b2)/10000)/10000);
            printf("d = %lf\n", d);
            fprintf(f1, "%lf %lf %lf %lf\n", q, r, s/10000);
            fprintf(f2, "%lf %lf %lf %lf\n", q, r, d1/d);
В чем может быть дело? Сто раз уже проверил код...
P.S. На лишние закомментированные выражения не обращайте внимания)))
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
gazlan
2861 / 1809 / 272
Регистрация: 27.08.2010
Сообщений: 4,893
Записей в блоге: 1
25.04.2013, 11:43     Расчёт дисперсии #2
Судя по выражениям вида s1 = s1 + , никакого понятия о языке С у вас нет. Константы везде, вместо double - целые. Наверняка, и тип переменной указан неверно и происходит округление до целого нуля.
GTG
0 / 0 / 0
Регистрация: 10.03.2013
Сообщений: 7
25.04.2013, 17:36  [ТС]     Расчёт дисперсии #3
Цитата Сообщение от gazlan Посмотреть сообщение
Судя по выражениям вида s1 = s1 + , никакого понятия о языке С у вас нет. Константы везде, вместо double - целые. Наверняка, и тип переменной указан неверно и происходит округление до целого нуля.
1. Константы, как и переменные, везде объявлены как double, просто я это не стал копировать.
2. Почему, если я написал
C++
1
s1 = s1 + ...
а не
C++
1
s1+=...
то это значит, что у меня "нет никакого понятия о языке С"?
gazlan
2861 / 1809 / 272
Регистрация: 27.08.2010
Сообщений: 4,893
Записей в блоге: 1
25.04.2013, 20:05     Расчёт дисперсии #4
Иными словами, в коде у вас все правильно, а для форума вы специально неверно написали?

Продолжайте...
GTG
0 / 0 / 0
Регистрация: 10.03.2013
Сообщений: 7
25.04.2013, 21:32  [ТС]     Расчёт дисперсии #5
Цитата Сообщение от gazlan Посмотреть сообщение
Иными словами, в коде у вас все правильно, а для форума вы специально неверно написали?

Продолжайте...
Я не думал о таких мелочах, как неверное указывание типа данных (double).
Меня до сих пор продолжает волновать вопрос неверного расчёта дисперсии.
gazlan
2861 / 1809 / 272
Регистрация: 27.08.2010
Сообщений: 4,893
Записей в блоге: 1
25.04.2013, 22:25     Расчёт дисперсии #6
Пока выбор правильного типа данных будет для вас "мелочью", верный расчет вы сможете получить, разве что, по ошибке. И 20+ строчек кода с простейшей арифметикой так и останутся неодолимым препятствием.

Исправьте ошибки, на которые вам указали, если все еще не будет работать - выложите заново полный код, так чтобы можно было проверить типы переменных и сам файл данных, на которых получаете ошибку - нет никакой гарантии, что они корректно записаны.
GTG
0 / 0 / 0
Регистрация: 10.03.2013
Сообщений: 7
25.04.2013, 23:21  [ТС]     Расчёт дисперсии #7
Цитата Сообщение от gazlan Посмотреть сообщение
Пока выбор правильного типа данных будет для вас "мелочью", верный расчет вы сможете получить, разве что, по ошибке. И 20+ строчек кода с простейшей арифметикой так и останутся неодолимым препятствием.

Исправьте ошибки, на которые вам указали, если все еще не будет работать - выложите заново полный код, так чтобы можно было проверить типы переменных и сам файл данных, на которых получаете ошибку - нет никакой гарантии, что они корректно записаны.
Какие ошибки? Говорю же, везде double. Вот полный код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <stdio.h>
 
int main () {
 
    double w0[20000];
    double wf[20000];
    double p[20000];
    double a, b, c;
    double q;
    double r;
    double s = 0;
    double s1 = 0;
    double d = 0;
    double d1 = 0;
    double h=1.0;
    double a1=0;
    double a2=0;
    double b1=0;
    double b2=0;
    //printf("Enter q\n");
    //scanf("%lf", &q);
    //printf("Enter r\n");
    //scanf("%lf", &r);
    printf("starting... \n");
    FILE *f;
    FILE *f1;
    FILE *f2;
    //f = fopen ("kalman.txt", "r");    
    if ((f1 = fopen("s.txt", "w")) == NULL)
        printf("file1 was not opened\n");
    if ((f2 = fopen("d.txt", "w")) == NULL)
        printf("file2 was not opened\n");
    for (double q=0.01; q<10; q+=0.01) {
        for (double r=0.0001; r<300; r+=10.0) {
            //f = fopen("data.txt", "r");
             if( (f  = fopen( "data.txt", "r" )) == NULL ) 
                 printf( "file was not opened\n" );
             //else
                 //printf("file was opened successfully");
 
            for (int i=0; i<10000; i++) {
                fscanf(f, "%lf  %lf %lf", &a, &w0[i], &c);
                //printf("%g\n", w0[i]);
                s1 = s1 + w0[i];
                a1 = a1 + w0[i]*w0[i];
                a2 = a2 + w0[i];
            }   
            //printf("s1 = %lf\n", s1/20000);
            //printf("d1 = %lf\n", a1/20000);
            wf[0] = w0[0];
            p[0] = 0;
            for (int i=1; i<10000; i++) {
                    p[i] = (1 - (p[(i-1)]/((p[(i-1)]+r)))) * p[(i-1)] + q;
                    wf[i] = (1 - (p[(i-1)]/((p[(i-1)]+r)))) * wf[(i-1)] + p[(i-1)]*w0[i]/((p[(i-1)]+r));
                    //printf("%g\n", wf[i]);
                    s = s + wf[i];  
                    b1 = b1 + wf[i]*wf[i];
                    b2 = b2 + wf[i];
                }
            //printf("s = %lf\n", s/20000);
            //printf("d1 = %lf\n", d/20000);
            d1 = a1/10000 - (((a2*a2)/10000)/10000);
            printf("d1 = %lf\n", d1);
            d = b1/10000 - (((b2*b2)/10000)/10000);
            printf("d = %lf\n", d);
            fprintf(f1, "%lf %lf %lf %lf\n", q, r, s/10000);
            fprintf(f2, "%lf %lf %lf %lf\n", q, r, d1/d);
             //if ( fclose( f ) )
            fclose(f);
            d=0;
            d1=0;
            a1=0;
            a2=0;
            b1=0;
            b2=0;
            s=0;
            s1=0;
     // {
      //   printf( "The file 'crt_fopen.c' was not closed\n" );
     // }
 
        }
    }  
}
//}
P.S. Присутствуют лишние закомментированные строки, а также, возможно, вывод данных в консоль, который не нужен
gazlan
2861 / 1809 / 272
Регистрация: 27.08.2010
Сообщений: 4,893
Записей в блоге: 1
26.04.2013, 01:19     Расчёт дисперсии #8
Цитата Сообщение от GTG Посмотреть сообщение
везде double
Издеваетесь? У вас везде целочисленные литералы.

Код сейчас посмотрю и отвечу.

Добавлено через 1 час 30 минут
Насколько смог, попытался исправить этот кошмар. О корректности ваших формул ничего не могу сказать, но очевидно, что у вас нет представления не только о C, но и о программировании вообще.

Почитайте хотя бы вводные главы (файлы, циклы) любого учебника.

И еще. Я уже писал в другом топике, как точка вместо запятой стоила американцам потери Mariner-1.

Пока идиомы языка, стиль форматирования кода, выбор корректного типа данных, регистра букв и имен переменных будут для вас "мелочью", вы обречены.

Good Luck !



C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdio.h>
#include <math.h>
#include <stdio.h>
 
#define  MAX_ARR_SIZE            (20000)
#define  OUTER_LOOP_CNT          (1000)
#define  INNERR_LOOP_CNT         (30)
#define  INPUT_LOOP_CNT          (10000)
#define  CALC_LOOP_CNT           (10000)
 
int main(int argc,char** argv)
{
   FILE*    pIn = fopen("data.txt","rt");
 
   if (!pIn)
   {
      printf("file In wasn't opened.\n");
      return 0;
   }
 
   double   pW1[MAX_ARR_SIZE];
   double   pW2[MAX_ARR_SIZE];
   double   pPP[MAX_ARR_SIZE];
 
   memset(pW1,0,sizeof(double) * MAX_ARR_SIZE);
   memset(pW2,0,sizeof(double) * MAX_ARR_SIZE);
   memset(pPP,0,sizeof(double) * MAX_ARR_SIZE);
 
   double   fSum  = 0.0;
   double   fSum2 = 0.0;
 
   for (int kk = 0; kk < INPUT_LOOP_CNT; ++kk)
   {
      char     pszTemp[MAX_PATH + 1];
 
      fgets(pszTemp,MAX_PATH,pIn);
 
      sscanf(pszTemp,"%Lf",&pW1[kk]);
 
      fSum  += pW1[kk];
      fSum2 += pW1[kk] * pW1[kk];
   }
 
   fclose(pIn);
   pIn = NULL;
 
   FILE*    pOut1 = fopen("s.txt","wt");
 
   if (!pOut1)
   {
      printf("File Out1 wasn't opened.\n");
      return 0;
   }
 
   FILE*    pOut2 = fopen("d.txt","wt");
 
   if (!pOut2)
   {
      printf("File Out2 wasn't opened.\n");
      return 0;
   }
 
   double   fA2 = fSum;
 
   double   qq = 0.01;
 
   for (int ii = 0; ii < OUTER_LOOP_CNT; ++ii, qq += 0.01)
   {
      double   rr = 0.0001;
 
      for (int jj = 0; jj < INNERR_LOOP_CNT; ++jj, rr += 10.0)
      {
         pW2[0] = pW1[0];
         pPP[0] = 0;
 
         double   fSum3 = fSum;
 
         double   fSum21 = 0.0;
         double   fSum22 = 0.0;
 
         for (int ll = 1; ll < CALC_LOOP_CNT; ++ll)
         {
            pPP[ll] = qq + pPP[(ll - 1)] * (1 - (pPP[(ll - 1)] / ((pPP[(ll - 1)] + rr))));
 
            pW2[ll] = (1 - (pPP[(ll - 1)] / ((pPP[(ll - 1)] + rr)))) * pW2[(ll - 1)] + pPP[(ll - 1)] * pW1[ll] / ((pPP[(ll - 1)] + rr));
 
            fSum3 += pW2[ll];
 
            fSum21 += pW2[ll] * pW2[ll];
            fSum22 += pW2[ll];
         }
 
         double   fD1 = 1.E-4 * fSum   - 1.E-8 * fA2    * fA2;
         double   fD2 = 1.E-4 * fSum21 - 1.E-8 * fSum22 * fSum22;
 
         fprintf(pOut1,"%lf %lf %lf %lf\n",qq,rr,1.E-4 * fSum3);
         fprintf(pOut2,"%lf %lf %lf %lf\n",qq,rr,fD1 / fD2);
      }
   }
 
   fclose(pOut1);
   fclose(pOut2);
 
   return 0;
}
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
26.04.2013, 03:33     Расчёт дисперсии #9
gazlan, При арифметических операциях типы неявно преобразуются к наибольшему. В данном случае все целочисленные константы преобразуются компилятором к типу double. Нет никакого смысла их менять в коде ТС на константы вещественного типа. Разница будет только если первыми операциями в выражении идет целочисленное деление ( что то вроде: double a = 100 / 33 * 0.1; в данном случае сначала будет произведено целочисленное деление, потом его результат будет неявно приведен к double. Здесь лучше или явно сделать одну из констант при делении вещественной, или же просто перенести умножение в начало.)
gazlan
2861 / 1809 / 272
Регистрация: 27.08.2010
Сообщений: 4,893
Записей в блоге: 1
26.04.2013, 05:22     Расчёт дисперсии #10
Цитата Сообщение от Toshkarik Посмотреть сообщение
неявно преобразуются к наибольшему
Формально, это преобразование находится внутри тройного вложенного цикла и должно выполняться 3 000 000 000 раз для каждого литерала.

Разумеется, оптимизирующий компилятор, такой как VC, должен вынести это преобразование за цикл, а в идеале, и вовсе выполнить во время компиляции и сразу подставить адрес внутреннего представления с двойной точностью. Тем не менее, всегда лучше обозначить свои намерения явно - так будет проще и для компилятора и для читающего код.

Кроме того, это самый мелкий из промахов автора. Например, внутри двойного цикла (30 000 раз), у него вставлен вызов fopen().

Так что, исправления не сводились к расстановке точек - код переписан чуть менее, чем полностью.
GTG
0 / 0 / 0
Регистрация: 10.03.2013
Сообщений: 7
26.04.2013, 08:00  [ТС]     Расчёт дисперсии #11
Цитата Сообщение от gazlan Посмотреть сообщение
Формально, это преобразование находится внутри тройного вложенного цикла и должно выполняться 3 000 000 000 раз для каждого литерала.

Разумеется, оптимизирующий компилятор, такой как VC, должен вынести это преобразование за цикл, а в идеале, и вовсе выполнить во время компиляции и сразу подставить адрес внутреннего представления с двойной точностью. Тем не менее, всегда лучше обозначить свои намерения явно - так будет проще и для компилятора и для читающего код.

Кроме того, это самый мелкий из промахов автора. Например, внутри двойного цикла (30 000 раз), у него вставлен вызов fopen().

Так что, исправления не сводились к расстановке точек - код переписан чуть менее, чем полностью.
Согласитесь, открывание в цикле fopen не повлечет за собой изменения результатов выводимых данных. Константы привел к double, однако все равно дисперсия считается за 0.
gazlan
2861 / 1809 / 272
Регистрация: 27.08.2010
Сообщений: 4,893
Записей в блоге: 1
26.04.2013, 08:35     Расчёт дисперсии #12
Цитата Сообщение от GTG Посмотреть сообщение
Согласитесь, открывание в цикле fopen
Не соглашусь.

Вы все еще напрочь не понимаете смысл того что вами сделано (или списано). Почитайте, наконец, хоть что-нибудь про операции с файлами.

Кроме того, в вашем коде есть и другая грубейшая ошибка. Перечитывайте вот это вот - до просветления:

Пока идиомы языка, стиль форматирования кода, выбор корректного типа данных, регистра букв и имен переменных будут для вас "мелочью", вы обречены.
И еще, ваших данных у меня нет, но на какой-то случайной выборке из 1000+ значений исправленный мной код формирует и d.txt и s.txt, и никаких нулей там нет.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.04.2013, 12:28     Расчёт дисперсии
Еще ссылки по теме:

C++ Расчёт сложного процента
Расчёт статистических параметров C++
C++ Неправильный математический расчёт

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
26.04.2013, 12:28     Расчёт дисперсии #13
Цитата Сообщение от gazlan Посмотреть сообщение
а в идеале, и вовсе выполнить во время компиляции
Не в идеале, а в любом случае он это делает во время компиляции.
Yandex
Объявления
26.04.2013, 12:28     Расчёт дисперсии
Ответ Создать тему
Опции темы

Текущее время: 11:22. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru