Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 03.07.2012, 09:29
ZolotukhinDen ZolotukhinDen вне форума
Прохожий
 
Регистрация: 03.07.2012
Сообщения: 5
Репутация: 10
По умолчанию Помогите избавиться от NaN

Необходимо смоделировать случайную потерю электроном при соударении с атомом. Случайная потеря энергии моделируется функцией:
Код:
Function EL(i:Integer):Real; 
  begin
    Randomize;
    gamma:=roundto((random),-3); //псевдослучайное число
    En:=0;
     for i:=0 to 20000 do
        begin
          En:=Ep*(1+i/20); // приращение энергии от 1 эВ с шагом i/20
          if (Gx(En)=gamma) then EL:=(En/Ep); // Gx(En) - это функция задающая вероятность величины потери энергии (до 3 знака)
        end;
   end;

Энергия которая осталась у электрона после потери считается так:

Function Energy(j:Integer):Extended;
    begin
    if j=1 then Energy:=E/Ep;
    if (j>1) then Energy:=Abs(Energy(j-1)-EL(j));
    end;
Админ: Пользуемся тегами при оформлении кода!
Проблема: если среди значений En не нашлось с точностью до 3 знака равного gamma, то программа вылетает, сообщая что Energy(j) = NaN. Пожалуйста, помогите дописать алгоритм так чтобы не возникало неопределенности

Последний раз редактировалось Admin, 03.07.2012 в 09:57.
Ответить с цитированием
  #2  
Старый 03.07.2012, 09:35
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
Вопрос

а что компилятор не выдает предупреждение:
Цитата:
Return value of function 'Energy' might be undefined
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 04.07.2012, 08:57
ZolotukhinDen ZolotukhinDen вне форума
Прохожий
 
Регистрация: 03.07.2012
Сообщения: 5
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
а что компилятор не выдает предупреждение:
Return value of function 'Energy' might be undefined

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

"Project Scattering.exe raised exeption class EInvalidOp with message: 'Invalid floating point operation'. Process stopped. Use Step or Run to continue"
Ответить с цитированием
  #4  
Старый 04.07.2012, 11:20
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Ну во первых:
Вызов Randomize вынести из EL, она должна вызываться один раз при старте программы.

Во вторых:
Что произойдет, если в 9-ой строке ни один Gx(en) на буден равен gamma, то есть присваивание ниразу не выполнится? У Вас скорее всего такой случай.
Ответить с цитированием
  #5  
Старый 04.07.2012, 11:24
Arvo Arvo вне форума
Прохожий
 
Регистрация: 03.07.2012
Сообщения: 29
Версия Delphi: XE2
Репутация: 10
По умолчанию

Код:
if (Gx(En)=gamma) then EL:=(En/Ep);

Вот после этого думаю надо добавить проверку на случай, если Gx(En)<>gamma
А точнее в самом начале функции присвоить Result какое-то значение.

Можно еще все это дело забабахать в еще один цикл while/repeat который выполняется пока не будет достигнуто условие Gx(En)=gamma. Сбособ конечно ужасный, но больше ничего не могу предложить. Если уж совсем жалко процессорного времени, то можно и сделать огранчение на кол-во итераций цикла. Но опять же придется задавать значение при невыполнении условий.
Ответить с цитированием
Этот пользователь сказал Спасибо Arvo за это полезное сообщение:
ZolotukhinDen (10.07.2012)
  #6  
Старый 04.07.2012, 11:30
Arvo Arvo вне форума
Прохожий
 
Регистрация: 03.07.2012
Сообщения: 29
Версия Delphi: XE2
Репутация: 10
По умолчанию

Цитата:
Сообщение от icWasya
Ну во первых:
Вызов Randomize вынести из EL, она должна вызываться один раз при старте программы.

Вообще-то сооовсем не обязательно. Randomize устанавливает переменную RandSeed, которая используется как случайные данные при генерации псевдослучайных чисел. Точно не знаю, но вроде она берет значение системного таймера. Можно не вызывать randomize, а самому установить RandSeed. Randomize следует вызывать каждый раз, когда надо получить новую серию псевдослучайных чисел.-
Ответить с цитированием
  #7  
Старый 04.07.2012, 11:59
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Цитата:
Сообщение от ZolotukhinDen
Не выдает
а должен)
в любом случае сделай чтобы Energy всегда что-то возвращала, либо Exception.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #8  
Старый 04.07.2012, 22:14
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Интересные рассчеты. Во-первых,
Цитата:
Код:
if (Gx(En)=gamma) then EL:=(En/Ep); 
Зачем искать (En/Ep), если заведомо известно что оно = (1+i/20);
Во-вторых, зачем передавать в функцию El() параметр i, если он внутри пробегает значения
Цитата:
Код:
for i:=0 to 20000 do
, и, как известно, делается неопределенным. Код построен неверно сначала, что тут говорить.
Ответить с цитированием
  #9  
Старый 10.07.2012, 09:51
ZolotukhinDen ZolotukhinDen вне форума
Прохожий
 
Регистрация: 03.07.2012
Сообщения: 5
Репутация: 10
По умолчанию

Цитата:
Сообщение от Arvo
Код:
if (Gx(En)=gamma) then EL:=(En/Ep);

Вот после этого думаю надо добавить проверку на случай, если Gx(En)<>gamma
А точнее в самом начале функции присвоить Result какое-то значение.

Можно еще все это дело забабахать в еще один цикл while/repeat который выполняется пока не будет достигнуто условие Gx(En)=gamma. Сбособ конечно ужасный, но больше ничего не могу предложить. Если уж совсем жалко процессорного времени, то можно и сделать огранчение на кол-во итераций цикла. Но опять же придется задавать значение при невыполнении условий.
Добавлял проверку на случай Gx(En)<>gamma, присваивая значение функции EL:=0, такой ошибки разумеется не наблюдалось, однако тогда вообще потерь энергии не было - у электронов как было например 5000 эВ, так и оставалось, и энергетический спектр - доля электронов с определенной потерей энергии - вообще был просто столбиком, что неправильно. Код как мне кажется изначально верен - ведь пока Nan не выскакивает, спектр строится нормально.
Ответить с цитированием
  #10  
Старый 10.07.2012, 11:26
Rat Rat вне форума
Активный
 
Регистрация: 12.09.2008
Сообщения: 391
Репутация: 6078
По умолчанию

[OFFTOP]Вот так потом ядерные реакторы и работают. Чернобыль, Фукусима-1. Ага - не слушают программистов.[/OFFTOP]
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:20.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter