Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Поиск радиуса и высоты цилиндрического бака


Автор: Studeht 5.1.2010, 14:59
Здравствуйте уважаемые эксперты! Вообщем нужно найти размеры бака, чтобы на него ушло наименьшее количество материала. Вот получившийся код:
Код
unit Unit1;

interface

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

type
  TMainForm = class(TForm)
    Edit_V: TEdit;
    Label_V: TLabel;
    Label_R0: TLabel;
    Label_H0: TLabel;
    Edit_R0: TEdit;
    Edit_H0: TEdit;
    Edit_Eps: TEdit;
    Label_Eps: TLabel;
    ButtonCalcResult: TButton;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure ButtonCalcResultClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Edit_V.Clear;
  Edit_R0.Clear;
  Edit_H0.Clear;
  Edit_Eps.Clear;
end;

function Determinant(R0,H0:extended):extended;
begin
  Result:=d_2F_dR_2(R0,H0)*d_2F_dh_2-d_2F_dR_2(R0,H0)*d_2F_dR_2(R0,H0);
end;


procedure TMainForm.ButtonCalcResultClick(Sender: TObject);
var V,R0,H0,Eps,Func,FuncR,FuncH,dx,dy:extended;
    CountIter:integer;
begin
  CountIter:=0;
  V:=StrToFloat(Edit_V.Text);
  R0:=StrToFloat(Edit_R0.Text);
  H0:=StrToFloat(Edit_H0.Text);
  Eps:=StrToFloat(Edit_Eps.Text);
  Func:=F(R0,H0,V);
  repeat
    inc(CountIter);
    FuncR:=dF_dR(R0,H0);
    FuncH:=dF_dH(R0);
    dx:=(d_2F_dh_2*FuncR-d_2F_dR_dh(R0)*FuncH)/Determinant(R0,H0);
    dy:=(d_2F_dR_2(R0,H0)*FuncH-d_2F_dR_dh(R0)*FuncR)/Determinant(R0,H0);
    R0:=R0-dx; H0:=H0-dy; Func:=F(R0,H0,V);
    Memo1.Lines.Add(FloatToStrF(R0,fffixed,2,2)+' '+FloatToStrF(H0,fffixed,8,2));
  until (sqrt(sqr(dx)+sqr(dy))<Eps);
end;

end.


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

Автор: ~FoX~ 5.1.2010, 15:13
FuncAndDerrivation Это кто такой?

Автор: Studeht 5.1.2010, 15:21
Прощу прощения, забыл выложить модуль.. Здесь впринипе сама функция которая вроде бы должна быть(не уверен т.к. с математикой туго)  и ее производные
Код
unit FuncAndDerrivation;

interface

function F(R,h,V:extended):extended;
function dF_dR(R,h:extended):extended;
function dF_dh(R:extended):extended;
function d_2F_dR_2(R,h:extended):extended;
function d_2F_dh_2:extended;
function d_2F_dR_dh(R:extended):extended;

implementation

function F;
begin
  Result:=Pi*sqr(R)*h-V;
end;

function dF_dR;
begin
  Result:=2*Pi*R*h;
end;

function dF_dh;
begin
  Result:=Pi*sqr(R);
end;

function d_2F_dR_2;
begin
  Result:=2*Pi*R*h;
end;

function d_2F_dh_2;
begin
  Result:=0;
end;

function d_2F_dR_dh;
begin
  Result:=2*Pi*R;
end;

end.
 


Впринипе с точки зрения математики, я пошел через формулу объема цилиндра. v=Pi*R^2*h, сответственно функция выглядит так: Pi*R^2*h-v=0..

Автор: Amphiluke 5.1.2010, 15:35
А объем бака — величина постоянная V = const?
Если да, то тут, вроде, никакие циклы не нужны… Одна математика и две формулы на выходе: для R и H, выраженных через V.

Автор: Studeht 5.1.2010, 15:40
Объем вводит пользователь.. Циклы нужны, потому что нужно решить именно метод Ньютона. Если его не использовать то там действительно всего 2 формулы, но проблема то именно в методе..

Автор: ~FoX~ 5.1.2010, 16:28
Studeht, При каких значениях она в цикл попадает? 

Автор: Studeht 5.1.2010, 16:37
Вот нашел некоторые ошибки, теперь получается всегда почти 0.. Выложу код и модуль(и на всякий случай прикрепил сам проет)
Код
unit Unit1;

interface

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

type
  TMainForm = class(TForm)
    Edit_V: TEdit;
    Label_V: TLabel;
    Label_R0: TLabel;
    Label_H0: TLabel;
    Edit_R0: TEdit;
    Edit_H0: TEdit;
    Edit_Eps: TEdit;
    Label_Eps: TLabel;
    ButtonCalcResult: TButton;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure ButtonCalcResultClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Edit_V.Clear;
  Edit_R0.Clear;
  Edit_H0.Clear;
  Edit_Eps.Clear;
end;

function Determinant(R0,H0:extended):extended;
begin
  Result:=d_2F_dR_2(H0)*d_2F_dh_2-d_2F_dR_dh(R0)*d_2F_dR_dh(R0);
end;


procedure TMainForm.ButtonCalcResultClick(Sender: TObject);
var V,R0,H0,Eps,Func,FuncR,FuncH,dx,dy:extended;
    CountIter:integer;
begin
  CountIter:=0;
  V:=StrToFloat(Edit_V.Text);
  R0:=StrToFloat(Edit_R0.Text);
  H0:=StrToFloat(Edit_H0.Text);
  Eps:=StrToFloat(Edit_Eps.Text);
  Func:=F(R0,H0,V);
  repeat
    inc(CountIter);
    FuncR:=dF_dR(R0,H0);
    FuncH:=dF_dH(R0);
    dx:=(d_2F_dh_2*FuncR-d_2F_dR_dh(R0)*FuncH)/Determinant(R0,H0);
    dy:=(d_2F_dR_2(H0)*FuncH-d_2F_dR_dh(R0)*FuncR)/Determinant(R0,H0);
    R0:=R0-dx; H0:=H0-dy; Func:=F(R0,H0,V);
    Memo1.Lines.Add(FloatToStrF(R0,fffixed,2,2)+' '+FloatToStrF(H0,fffixed,8,2));
  until (sqrt(sqr(dx)+sqr(dy))<Eps);
end;

end.


Код

unit FuncAndDerrivation;

interface

function F(R,h,V:extended):extended;
function dF_dR(R,h:extended):extended;
function dF_dh(R:extended):extended;
function d_2F_dR_2(h:extended):extended;
function d_2F_dh_2:extended;
function d_2F_dR_dh(R:extended):extended;

implementation

function F;
begin
  Result:=Pi*sqr(R)*h-V;
end;

function dF_dR;
begin
  Result:=2*Pi*R*h;
end;

function dF_dh;
begin
  Result:=Pi*sqr(R);
end;

function d_2F_dR_2;
begin
  Result:=2*Pi*h;
end;

function d_2F_dh_2;
begin
  Result:=0;
end;

function d_2F_dR_dh;
begin
  Result:=2*Pi*R;
end;

end.
 

Автор: ~FoX~ 5.1.2010, 17:31
Studeht, Еще раз....При каких значениях?
У меня и первый и второй варианты работают, первый ни в какой цикл не попадает, второй выдает значения сильно отличные от нуля... Не знаю расчитывает он верно или нет, самому считать лениво...

Автор: Studeht 5.1.2010, 17:36
Хм.. Странно, но вот втророй вариант например ввожу: сответственно 48; 2,95; 3,5; 0,01.
Выдает следующее:
1,50 1,75
0,74 0,88
0,37 0,44
0,18 0,22
0,09 0,11
0,05 0,05
0,02 0,03
0,01 0,01
0,01 0,01

Хотя последней цифрой должен быть ответ(2,4)

Автор: Amphiluke 5.1.2010, 18:09
Цитата(Studeht @  5.1.2010,  18:40 Найти цитируемый пост)
Объем вводит пользователь..

А интересно, зачем? Вот вы пишите в своем коде:
Цитата(Studeht)

Код

V:=StrToFloat(Edit_V.Text);


и больше нигде эта величина не используется… Также и некоторые другие (обратите внимание на hints в отчете компилятора). Получается, решение от объема бака не зависит? O_o

Добавлено через 3 минуты и 8 секунд
Точнее, V используется здесь:
Цитата(Studeht)

Код

Func:=F(R0,H0,V);


но вот уже Func нигде не используется, что, впрочем, то же самое.

Автор: Studeht 5.1.2010, 18:13
Ну как, объем используется в изначальной формуле, вызываемой из модуля..

Добавлено через 48 секунд
Код
function F;
begin
  Result:=Pi*sqr(R)*h-V;
end;


Автор: Amphiluke 5.1.2010, 18:18
Да, это верно, но результат, возвращаемый этой ф-цией и присваеваемый в переменную Func не используется нигде.

Автор: Studeht 5.1.2010, 18:18
Уже голова болит, целый день сижу.. Сейчас буду смотреть..
Получается чтобы я не вводил, выдает одно и тоже smile 

Автор: Amphiluke 5.1.2010, 18:19
Компилятор-то не обманешь. Наверное.
Pardon, думал сообщение склеится с моим предыдущим...

Автор: Staruha 8.1.2010, 13:52
На мой взгляд наименьшее кол-во металла уйдет(В смысле с учетом отхода.Расход металла всегда будет одинаков) при H=D=2R
V=2R*pi*sqr®
находим R
Конечно ,если все это не ограничивается размером листа

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)