2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 Решения ряда. При больших порядках программа выдает ошибку
Сообщение26.09.2010, 20:35 


03/04/10
38
Задание заключается в следующем: нужно вычислить значение функционального ряда $arcsin(x)$ до N-го порядка малости.

Ряд задан формулой: $arcsin(x)=x+\frac 1 {2*3}x^3+\frac {1*3}{2*4*5}x^5+\frac{1*3*5}{2*4*6*7}x^7+...$
Сразу задался вопросом, какой будет общий член у этого ряда. Свёл к следующему:
$\sum_{i=1}^n \frac{(-1)^2...(2(i-1)-1)^2}{(2i-1)!}x^{2i-1}$

Теперь нужно было реализовать программу, вот она:
код: [ скачать ] [ спрятать ]
Используется синтаксис Pascal
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Math;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
function proizv(n:integer):integer;
begin
if n>0 then
proizv:=sqr(2*n-1)*proizv(n-1)
else
proizv:=1;
end;
function factorial(p:integer):integer;
begin
if p>1 then
factorial:=p*factorial(p-1)
else
factorial:=1;
end;

procedure TForm1.Button1Click(Sender: TObject);
var summ,x:real; n,i,p:integer;
begin
x:=strtofloat(edit1.Text);
n:=strtoint(edit2.Text);
i:=1;
summ:=0;
repeat
p:=2*i-1;
summ:=summ+(proizv(i-1)/factorial(p))*power(x,p);
i:=i+1;
until (i>n);
label1.caption:=floattostrf(summ,fffixed,6,3);

end;

end.


А теперь о проблеме.. Программа считает только малые порядки, у меня на n=15 программа ещё работает нормально, но при n=20 вылазиет ошибка:
Цитата:
project Project1.exe raised exception class EZeroDivide with message 'Floating point division by zero' Process stopped. Use Step or Run to continue
Не знаю как с этим бороться, может кто подскажет что я не так сделал? :roll:

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение26.09.2010, 22:00 
Заслуженный участник


27/04/09
28128
Elarium в сообщении #356489 писал(а):
Не знаю как с этим бороться, может кто подскажет что я не так сделал? :roll:
Как там ясно написано, вы делите на ноль.

P. S. Объявление function factorial(...) ужасно. Переделайте по-нормальному.

-- Пн сен 27, 2010 01:02:06 --

P. P. S. Остальной код не смотрел.

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение26.09.2010, 22:46 


03/04/10
38
arseniiv в сообщении #356516 писал(а):
Elarium в сообщении #356489 писал(а):
Не знаю как с этим бороться, может кто подскажет что я не так сделал? :roll:
Как там ясно написано, вы делите на ноль.

P. S. Объявление function factorial(...) ужасно. Переделайте по-нормальному.

-- Пн сен 27, 2010 01:02:06 --

P. P. S. Остальной код не смотрел.


Ну я попробую, но страно то, что для N<18 счет идет нормальный и на ноль ничего не делиться. :twisted:

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение26.09.2010, 22:51 
Заблокирован


18/09/10

183
Elarium писал(а):
что я не так сделал?

Все не так сделали.

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 05:45 
Заслуженный участник


04/05/09
4593
У Вас переполнение integer при вычислении факториала, да и proizv() тоже.
До некоторого n вычисляемое значение факториала просто неправильное, а далее, когда в факториале наберётся достаточное количество делителей двоек, Ваша функция factorial() вообще будет возвращать ноль, отсюда и ошибка.
Простейшее исправление - изменить тип функций factorial() и proizv() на real.
Других ошибок не искал.

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 08:18 
Заблокирован


18/09/10

183
venco

Надо начать с изменения алгоритма: так ряды не суммируют.

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 08:33 


03/04/10
38
y_nikolaenko в сообщении #356588 писал(а):
venco

Надо начать с изменения алгоритма: так ряды не суммируют.

Ну и как же их суммируют, если не секрет? :mrgreen:

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 09:14 
Заслуженный участник


11/05/08
32166
venco в сообщении #356571 писал(а):
До некоторого n вычисляемое значение факториала просто неправильное, а далее, когда в факториале наберётся достаточное количество делителей двоек, Ваша функция factorial() вообще будет возвращать ноль,

Так и есть. Тип integer (в дельфях) -- четырёхбайтовый, и как раз $33!=(2\cdot17-1)!$ нуля ещё не даёт (хотя даёт, конечно, чёрт-те что вместо истинного факториала, последнее правильное значение получается для $12!$), а $34!$, тем более $35!=(2\cdot18-1)!$ -- уже возвращает ноль.

Но главная проблема, конечно, в нелепости алгоритма. Во-первых, как уже было сказано y_nikolaenko, степенные ряды надо суммировать так:

Код:
y:=x;
S:=y;
for i:=1 to n do begin
    y:=y * <соответственно> * sqr(x);
    S:=S + y;
end;
(и, кстати, исходный вид разложения арксинуса гораздо приятнее для программирования, чем выражение с факториалами).

А во-вторых, нормальные люди не смешивают вычислительные и интерфейсные фрагменты в одну кучу. Какой ещё Button-то?... При чём тут вообще Button?... Выделите вычислительную часть в отдельную процедуру -- и ссылайтесь на неё по мере необходимости.

Ну и, конечно, выводить текст программы без отступов -- неприлично. Пользуйтесь тегом [ code].

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 14:33 
Заслуженный участник


27/04/09
28128

(Об отступах)

Ну, если заменить в том отрывке [quote] на [code] или даже [syntax=Pascal], отступы там сами не появятся. :-)

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 14:52 
Заслуженный участник
Аватара пользователя


11/03/08
10039
Москва
Выражение для общего члена ряда, при всей формально-математической правильности, для расчёта непригодно. Вычисления на ЭВМ всегда проводятся в конечной арифметике (ну... можно придумать тип данных, который позволил бы хранить произвольно большие числа... Но это спортивное достижение, а не прикладное; И, во всяком случае, если Вы ограничиваетесь стандартными типами языка, а не придумываете свои, нужно помнить их ограничения). Использование чисел, "не влезающих" в ячейку, отведенную под число, приводит к ошибке, причём может быть включена проверка выхода за границы диапазона (и тогда у Вас будет ясное сообщение, где вылетели), или отключена (и тогда в Вас в месте, где образуется ошибка, всё пройдёт, а вылетит совсем в другом месте).
В данном случае у Вас считается факториал, чрезвычайно быстро растущая функция ("продолжай далее - ты получишь числа, которые язык отказывается произнести, а рука записать" - а ведь автор "Книги Зогар" довёл таблицу факториалов лишь до 7!) и 20!=2432902008176640000 заведомо не влезет в разрядную сетку (максимальное число, представимое 4-мя байтами со знаком, есть 2147483647) и, скорее всего, бред пошёл, начиная с 12!. Разряды, не вмещавшиеся в 4 байта, просто обрубались, и к желаемым вычислениям отношения не имели.
Однако в Вашем случае нет надобности изобретать способ представления сверхдлинных чисел.
Достаточно сравнить два последовательных члена ряда. Отношение второго к первому будет весьма простым выражением (не забывайте про знак!), так что следующий член получается умножением уже имеющегося предыдущего на это выражение. Числа, которые там фигурируют, невелики и не вызовут переполнения.
Да, и чтоб два раза не вставать. Вычисление факториала рекурсией, при всей формальной правильности, решение не очень умное. Вызов функций достаточно накладная процедура, и работать будет крайне медленно. Если же ещё есть ограничения на глубину вложения вызовов (зависит от реализации компилятора), то у Вас вообще может не работать.

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 14:52 
Админ форума
Аватара пользователя


19/03/10
8952

(Об отступах)

arseniiv в сообщении #356640 писал(а):
Ну, если заменить в том отрывке
Цитата:
на [code] или даже [syntax=Pascal], отступы там сами не появятся. :-)
Если их изначально не было, то, конечно, не появятся. А если были, то теги [code] или [syntax] их покажут (в отличие от [quote] или простого текста).

(Вставил syntax в исходное сообщение).

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 15:27 
Заслуженный участник


11/05/08
32166

(Оффтоп)

Евгений Машеров в сообщении #356645 писал(а):
и, скорее всего, бред пошёл, начиная с 12!.

Нет, на 12-ти всё ещё верно, бред -- с 13-ти.

Евгений Машеров в сообщении #356645 писал(а):
Выражение для общего члена ряда, при всей формально-математической правильности, для расчёта непригодно.

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

Евгений Машеров в сообщении #356645 писал(а):
Вызов функций достаточно накладная процедура, и работать будет крайне медленно.

Наверное, медленно, но вовсе не крайне. В конце концов, вызов функции -- всего лишь две команды типа перехода, пусть и дальнего. Плюс загон операнда в стек, но это вообще тьфу.

Евгений Машеров в сообщении #356645 писал(а):
Если же ещё есть ограничения на глубину вложения вызовов (зависит от реализации компилятора), то у Вас вообще может не работать.

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

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 18:03 
Заслуженный участник
Аватара пользователя


11/03/08
10039
Москва
Ну, не знаю, ряд, где менее сотни членов ещё очень далеко от решения, как-то не вполне невозможен...

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение27.09.2010, 23:01 
Заслуженный участник


11/05/08
32166

(Оффтоп)

Евгений Машеров в сообщении #356695 писал(а):
Ну, не знаю, ряд, где менее сотни членов ещё очень далеко от решения, как-то не вполне невозможен...

Нет, не невозможен, конечно. Но что неразумен -- то точно. В типичных ситуациях, и при разумных подходах к способу аппроксимации -- количество членов имеет примерно тот же порядок, что и количество получаемых при этом значащих цифр.

Конкретно для арксинуса, в качестве примера. Если аргумент не превышает половинки, скажем, то шибко много членов и не понадобится. Но если он, наоборот, приближается к единичке -- то использование конкретно этого ряда становится явно неадекватным. Ну и кто ж виноват, коли приспичивает его использование в неподходящей ситуации?...

 Профиль  
                  
 
 Re: Решения ряда. При больших порядках программа выдает ошибку
Сообщение28.09.2010, 18:30 
Заслуженный участник
Аватара пользователя


11/03/08
10039
Москва
С арксинусом ситуация приятная. Там есть очевидные приведения к "хорошим" значениям аргумента. Увы, не всегда везёт.

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

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



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

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


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

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