Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/6: Рейтинг темы: голосов - 6, средняя оценка - 4.50
GTG
0 / 0 / 0
Регистрация: 10.03.2013
Сообщений: 7
1

Расчёт дисперсии

25.04.2013, 08:28. Просмотров 1151. Ответов 12
Метки нет (Все метки)

Привет!
У меня возникла странная проблема - при считывании столбца данных из текстового файла (данных около 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. На лишние закомментированные выражения не обращайте внимания)))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.04.2013, 08:28
Ответы с готовыми решениями:

Расчёт площади для парковки авто (тип авто, площадь, расчёт средней общей)
Расчёт площади для парковки авто (тип авто, площадь, расчёт средней общей)....

Вычисление дисперсии
Составьте пожалуйста программу для нахождения дисперсии, среднего квадратичного...

Cоставить формулу дисперсии для массива чисел
Есть массив arr. Нужно составить формулу для вычисления дисперсии. К сожалению...

Составить программу вычисления дисперсии 10 произвольно заданных чисел
Нужно реализовать программу с помощью for ,while,do while.

Вычислить среднее и оценку дисперсии значений введенных элементов массива.
Помогите с задачкой Введя значение n из диапазона (0&lt;n&lt;=100) и значения n...

12
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
25.04.2013, 11:43 2
Судя по выражениям вида s1 = s1 + , никакого понятия о языке С у вас нет. Константы везде, вместо double - целые. Наверняка, и тип переменной указан неверно и происходит округление до целого нуля.
0
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+=...
то это значит, что у меня "нет никакого понятия о языке С"?
0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
25.04.2013, 20:05 4
Иными словами, в коде у вас все правильно, а для форума вы специально неверно написали?

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

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

Исправьте ошибки, на которые вам указали, если все еще не будет работать - выложите заново полный код, так чтобы можно было проверить типы переменных и сам файл данных, на которых получаете ошибку - нет никакой гарантии, что они корректно записаны.
0
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. Присутствуют лишние закомментированные строки, а также, возможно, вывод данных в консоль, который не нужен
0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 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;
}
0
Toshkarik
1149 / 866 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
26.04.2013, 03:33 9
gazlan, При арифметических операциях типы неявно преобразуются к наибольшему. В данном случае все целочисленные константы преобразуются компилятором к типу double. Нет никакого смысла их менять в коде ТС на константы вещественного типа. Разница будет только если первыми операциями в выражении идет целочисленное деление ( что то вроде: double a = 100 / 33 * 0.1; в данном случае сначала будет произведено целочисленное деление, потом его результат будет неявно приведен к double. Здесь лучше или явно сделать одну из констант при делении вещественной, или же просто перенести умножение в начало.)
0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
26.04.2013, 05:22 10
Цитата Сообщение от Toshkarik Посмотреть сообщение
неявно преобразуются к наибольшему
Формально, это преобразование находится внутри тройного вложенного цикла и должно выполняться 3 000 000 000 раз для каждого литерала.

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

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

Так что, исправления не сводились к расстановке точек - код переписан чуть менее, чем полностью.
0
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.
0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
26.04.2013, 08:35 12
Цитата Сообщение от GTG Посмотреть сообщение
Согласитесь, открывание в цикле fopen
Не соглашусь.

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

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

Пока идиомы языка, стиль форматирования кода, выбор корректного типа данных, регистра букв и имен переменных будут для вас "мелочью", вы обречены.
И еще, ваших данных у меня нет, но на какой-то случайной выборке из 1000+ значений исправленный мной код формирует и d.txt и s.txt, и никаких нулей там нет.
0
Toshkarik
1149 / 866 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
26.04.2013, 12:28 13
Цитата Сообщение от gazlan Посмотреть сообщение
а в идеале, и вовсе выполнить во время компиляции
Не в идеале, а в любом случае он это делает во время компиляции.
0
26.04.2013, 12:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.04.2013, 12:28

Расчёт суммы
Задача. Написать программу для расчета суммы

Типовой расчёт
Помогите, пожалуйста, решить дифференциальное уравнение: y'-y/x=1+1/x

Расчёт по формуле
2) В другой задаче нужно произвести по этой формуле расчет. Я пока сделал...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru