2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 нужна помощь
Сообщение24.11.2009, 01:10 


09/11/09
21
В общем, уже долго не могу понять, что я не так делаю.
Код:
srand(time(0));
      for(i=1;i<=N;i++)
      {                        
                 tao_1=0.;         
         theta=PI/2.-h_0;               
         while(1)
         {
            STEP1:      
            r=double(rand())/double(RAND_MAX);            
            tao_1=tao_1-cos(theta)*log(1.-r);         
            if(tao_1>0. & tao_1<tao_0)
            {
               if(r>albedo_disp)
               {
                  break;
               }
               else
               {
                  cos_gamma=2.*r*(1.+pow(g,2.))*(g*r+1.-g)-pow((1.-g),2.)/pow((2.*g*r+1.-g),2.);
                  sin_gamma=sqrt(1.-pow(cos_gamma,2.));
                  cos_theta=cos(theta)*cos_gamma+sin(theta)*sin_gamma*sin(2.*PI*r);
                  theta=acos(cos_theta);
                  goto STEP1;
               }
            }   
            else   
            {   
               if(tao_1>tao_0)
               {
                  F_down=F_down+1.;
                  if(r>albedo_surf)
                  {
                     break;                     
                  }
                  else
                  {   
                 tao_1=tao_0;
                     theta=PI/2.+r*PI/2.;
                     goto STEP1;
                  }   
               }
               else
               {
                  if(tao_1<0.)
                  {   
                     F_up=F_up+1.;
                     break;
                  }             
               }                                             
      
            }            
         }         
      }

Проблема в том что за один шаг цикла for значение переменной F_down время от времени изменяется больше чем на 1, чего быть не должно. Вторая проблема в том что если задать N достаточно большим, то программа вообще перестает работать, начиная с некоторого момента (не сразу) она не выходит из цикла while, при этом многие переменные получаются равными #ind00. Я так понимаю это деление 0 на 0, только откуда оно там. Если кто видит, что не так - дайте знать.

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 01:44 
Заслуженный участник


09/08/09
3438
С.Петербург
Первое, что бросается в глаза - это использование битовой операции '&' вместо логической '&&'
Код:
            if(tao_1>0. & tao_1<tao_0)
Кроме этого, если бы Вы объяснили хотя бы в двух словах, что Ваша программа должна делать, помочь Вам было бы существенно проще.
И наконец, попробуйте переписать программу без этого кошмарного ( :) ) goto. Я Вас уверяю: проблем с логикой работы после этого станет гораздо меньше.

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 04:51 
Заслуженный участник


04/05/09
4587
Maslov в сообщении #264840 писал(а):
Первое, что бросается в глаза - это использование битовой операции '&' вместо логической '&&'
Код:
            if(tao_1>0. & tao_1<tao_0)
В данном случае это не важно, т.к. здесь операнды битового & - булевые выражения.

-- Пн ноя 23, 2009 20:54:59 --

Maslov в сообщении #264840 писал(а):
И наконец, попробуйте переписать программу без этого кошмарного ( :) ) goto. Я Вас уверяю: проблем с логикой работы после этого станет гораздо меньше.
Здесь напрашивается использование continue, но всё же проблемы с пониманием goto в данном коде, по моему, преувеличены. ;)

-- Пн ноя 23, 2009 21:01:40 --

Я вижу такие проблемы.
Во первых, r может оказаться точно равным 1., что приведёт к логарифму нуля (- бесконечность), и, скорее всего, сломает алгоритм (который мне тоже не понятен).
Во вторых, если tau_1 окажется точно равен 0. или tau_0 (возможно маловероятное событие), то не исполнится код ни в одной ветке if. Может быть, в это и не приведёт к ошибке. Я не знаю.

-- Пн ноя 23, 2009 21:09:45 --

При вычислении cos_gamma и sin_gamma нет проверок на валидность операндов pow() и sqrt(). Я не знаю, могут ли там получиться отрицательные числа, но если вдруг получатся, то theta станет равно nan (not a number), и после этого tau_1 тоже будет равно nan, и while намертво зациклится.
На всякий случай напоминаю, что любая операция с nan даёт nan, а любое сравнение с nan даёт false.

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 12:39 
Заслуженный участник


09/08/09
3438
С.Петербург
venco в сообщении #264849 писал(а):
В данном случае это не важно, т.к. здесь операнды битового & - булевые выражения.
И тем не менее, на мой взгляд, использование & вместо && говорит или о непонимании разницы, или о некоторой неряшливости программирования. В обоих случаях мне кажется уместным обратить внимание автора на это обстоятельство.

venco в сообщении #264849 писал(а):
Здесь напрашивается использование continue
Ну это кому как. У меня, например, напрашивается использование цикла while с явно прописанным в заголовке цикла условием окончания.

venco в сообщении #264849 писал(а):
проблемы с пониманием goto в данном коде, по моему, преувеличены
Да проблем-то с пониманием goto вообще никаких, но вот у автора, как мне показалось, имеются проблемы с пониманием логики работы программы, а структурное программирование придумано как раз для того, чтобы сделать эту логику более прозрачной.
Во избежание недоразумений, хочу отметить, что вышесказанное является сугубо частным мнением и ни в коем случае не должно расцениваться как призыв к началу очередной священной goto-войны. :)

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 19:08 
Заслуженный участник


26/07/09
1559
Алматы
2venco
Цитата:
В данном случае это не важно, т.к. здесь операнды битового & - булевые выражения.

Дело в том, что приоритет оператора & выше приоритета операторов < и >, а приоритет && -- наоборот, очень маленький. То есть, код if(tao_1>0. & tao_1<tao_0) не эквивалентен коду if((tao_1>0.) & (tao_1<tao_0)) и не эквивалентен коду if(tao_1>0. && tao_1<tao_0). Можно попробовать поиграть со скобками.

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 19:14 
Заслуженный участник


04/05/09
4587
Circiter в сообщении #264986 писал(а):
Дело в том, что приоритет оператора & выше приоритета операторов < и >
О! Точно! Как я это не заметил? :oops:

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 19:36 
Заслуженный участник


09/08/09
3438
С.Петербург
venco в сообщении #264988 писал(а):
Circiter в сообщении #264986 писал(а):
Дело в том, что приоритет оператора & выше приоритета операторов < и >
О! Точно! Как я это не заметил? :oops:
Извините, Circiter и venco, вы о чём? Насколько я помню, по приоритету между & и && стоят только | и ^.
Да и не мог компилятор понять
Код:
if(tao_1>0. & tao_1<tao_0)
как
Код:
if(tao_1>(0. & tao_1)<tao_0)
На мой взгляд, это бы просто не откомпилировалось :).
Или я что-то упустил?

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 19:44 
Заслуженный участник


26/07/09
1559
Алматы
2Maslov
Я ошибся. Спутал приоритет побитового & с приоритетом ссылочного &. :) Так что, venco был прав, разницы нет.

-- Вт ноя 24, 2009 22:52:13 --

2lukashev_sergey
Цитата:
Проблема в том что за один шаг цикла for значение переменной F_down время от времени изменяется больше чем на 1, чего быть не должно.

Фрагмент
код: [ скачать ] [ спрятать ]
Используется синтаксис C
               if(tao_1>tao_0)
               {
                  F_down=F_down+1.;
                  if(r>albedo_surf)
                  {
                     break;                    
                  }
                  else
                  {  
                 tao_1=tao_0;
                     theta=PI/2.+r*PI/2.;
                     goto STEP1;
                  }  
               }
 

расположен после метки STEP1 и содержит goto-переход на эту метку, т.е. несколько инкрементов F_down за одну for-итерацию вполне ожидаемы.

 Профиль  
                  
 
 Re: нужна помощь
Сообщение24.11.2009, 23:27 


09/11/09
21
Хух...
Цитата:
Первое, что бросается в глаза - это использование битовой операции '&' вместо логической '&&'
Исправил, эффект нулевой. Прочитал в книжке что операция & вообще применима только к целочисленным операндам, если так, то как оно вообще хоть как-то работало.

Цитата:
И тем не менее, на мой взгляд, использование & вместо && говорит или о непонимании разницы, или о некоторой неряшливости программирования.
С этим я пожалуй соглашусь.Как и с этим:
Цитата:
проблемы с пониманием goto в данном коде, по моему, преувеличены.
Я написал самый простой для меня код программы.

Цитата:
Фрагмент расположен после метки STEP1 и содержит goto-переход на эту метку, т.е. несколько инкрементов F_down за одну for-итерацию вполне ожидаемы.
Хотелось бы узнать засчет чего конкретно это происходит, поскольку соображения из которых писалась программа исключают это.

Цитата:
Кроме этого, если бы Вы объяснили хотя бы в двух словах, что Ваша программа должна делать, помочь Вам было бы существенно проще.
Здесь осуществляется статистическое моделирование, моделируется поведение фотона(рассеяние, поглощение, отражение от поверхности). Параметры этих событий носят вероятностный характер, поэтому для этих целей генерируется случайное число.

 Профиль  
                  
 
 Re: нужна помощь
Сообщение25.11.2009, 00:40 
Заслуженный участник


26/07/09
1559
Алматы
Цитата:
Хотелось бы узнать засчет чего конкретно это происходит, поскольку соображения из которых писалась программа исключают это.

Что-то из законов Мэрфи. Если что-то может случиться, то это случается. :) Если goto на метку есть, то рано или поздно он выполнится, то есть зачем-то же вы его написали... Да и сам while(1) может привести к лишним инкрементам...

Запустите пошаговую трассировку кода под отладчиком в вашей IDE и посмотрите как именно происходит выполнение алгоритма (или просто добавьте отладочную печать, в тех же целях).

 Профиль  
                  
 
 Re: нужна помощь
Сообщение25.11.2009, 02:26 
Заслуженный участник


09/08/09
3438
С.Петербург
А Вы не могли бы привести более полный фрагмент Вашего кода, включающий, по крайней мере, присваивания всем переменным, которые должны быть инициализированы (h_0, tao_0, N и т.п.), а также вывод того, что, собственно, считается (я, например, этого так и не понял).

 Профиль  
                  
 
 Re: нужна помощь
Сообщение27.11.2009, 20:30 


09/11/09
21
Maslov в сообщении #265143 писал(а):
А Вы не могли бы привести более полный фрагмент Вашего кода, включающий, по крайней мере, присваивания всем переменным, которые должны быть инициализированы (h_0, tao_0, N и т.п.), а также вывод того, что, собственно, считается (я, например, этого так и не понял).
Вот полный код:
Код:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include <time.h>

main()
{   
   double PI=3.1415926;
   int i,N=1000;
   double   
   F_down, 
   F_up, 
   h_0, 
   tao_0, 
   albedo_disp, 
   g, 
   albedo_surf, 
   F_down_0,
   tao_1,
   theta,
   r,
   cos_gamma,
   sin_gamma,
   cos_theta,
   F_atm,
   F_surf,
   F_refl;
   
      
   h_0=PI/3.;
   tao_0=0.3;
   albedo_disp=0.7;
   g=0.5;
   albedo_surf=0.5;
   F_down_0=1.;   
   F_down=0.;
   F_up=0.;

      srand(time(0));
      for(i=1;i<=N;i++)
      {
         tao_1=0.;
         theta=PI/2.-h_0;         
         while(1)
         {
            STEP1:      
            r=double(rand())/double(RAND_MAX);
            tao_1=tao_1-cos(theta)*log(1.-r);                                 
            if(tao_1>0. && tao_1<tao_0)
            {
               if(r>albedo_disp)
               {
                  break;
               }
               else
               {
                  cos_gamma=2.*r*(1.+pow(g,2.))*(g*r+1.-g)-pow((1.-g),2.)/pow((2.*g*r+1.-g),2.);
                  sin_gamma=sqrt(1.-pow(cos_gamma,2.));
                  cos_theta=cos(theta)*cos_gamma+sin(theta)*sin_gamma*sin(2.*PI*r);
                  theta=acos(cos_theta);               
                  goto STEP1;
               }
            }   
            else   
            {   
               if(tao_1>tao_0)
               {
                  F_down=F_down+1.;
                  if(r>albedo_surf)
                  {
                     break;
                     
                  }
                  else
                  {   tao_1=tao_0;
                     theta=PI/2.+r*PI/2.;                  
                     goto STEP1;
                  }   
               }
               else
               {
                  if(tao_1<0.)
                  {   
                     F_up=F_up+1.;
                     break;
                  }
             
               }                                             
               
            }
            
         }
         
      }
   F_down=F_down/double(N);
   F_up=F_up/double(N);
   F_refl=albedo_surf*F_down;
   F_surf=1.-F_refl;
   F_atm=F_down_0-F_up-F_down+F_surf;
   printf("%lf %lf %lf %lf %lf\n",F_down,F_up,F_refl,F_surf,F_atm);
}
   

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group