Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Прораммирование алгоритмов цикличной структуры

Автор: Mambakremen 13.11.2010 15:24

Задание
Найти сумму Y=F1(x)/F2(x), где a<=x<=b, x менятется с шагом h=c. Задано F1(x)=exp((1/5)*ln(6*x-x*x)), F2(x)=sin(exp(2*x)*ln(x))-cos(x), a=3.5, b=6.5, c=0.2.(Сам писал функции может ошибся smile.gif ) Сделать два варианта программы с использованием циклов for & repeat.

Цикл for - ошибка 207

program summa;
uses crt;
const
a=3.5;
b=6.5;
c=0.2; {wag h}
var x,y,F1,F2:real;i,n:integer;
begin
writeln('Summa funrcuu y=F1(x)/F2(x)');
x:=a;
n:=round((b-a)/c)+1;
for i:=1 to n do
begin
F1:=exp((1/5)*ln(6*x-x*x));
F2:=sin(exp(2*x)*ln(x))-cos(x);
y:=y+(F1/F2);
x:=x+c;
end;
writeln(y:1:2);
readkey;
end.



Цикл repeat - ошибка 207

program summa;
uses crt;
const
a=3.5;
b=6.5;
c=0.2; {wag h}
var x,y,F1,F2:real;i,n:integer;
begin
clrscr;
writeln('Summa funrcuu y=F1(x)/F2(x)');
x:=a;
repeat
F1:=exp((1/5)*ln(6*x-x*x));
F2:=sin(exp(2*x)*ln(x))-cos(x);
y:=y+(F1/F2);
x:=x+c;
until x>b;
writeln(y:1:2);
readkey;
end.

Автор: volvo 13.11.2010 15:29

Добавь строчку:

for i:=1 to n do
begin
writeln(6*x-x*x:10:6); { <--- Вот эту }
F1:=exp((1/5)*ln(6*x-x*x));
F2:=sin(exp(2*x)*ln(x))-cos(x);
y:=y+(F1/F2);
x:=x+c;
end;

, и запусти программу. А потом подумай, почему при таком значении аргумента Ln программа вылетает. И исправляй smile.gif

Автор: Mambakremen 13.11.2010 15:33

Цитата(volvo @ 13.11.2010 10:29) *

Добавь строчку:
for i:=1 to n do
begin
writeln(6*x-x*x:10:6); { <--- Вот эту }
F1:=exp((1/5)*ln(6*x-x*x));
F2:=sin(exp(2*x)*ln(x))-cos(x);
y:=y+(F1/F2);
x:=x+c;
end;

, и запусти программу. А потом подумай, почему при таком значении аргумента Ln программа вылетает. И исправляй smile.gif


Блин, добавил, та же дрянь 207 и все, извини, но не пойму... wacko.gif

Автор: volvo 13.11.2010 15:43

Я не сказал "добавь и эта ошибка уйдет". Я сказал "добавь и посмотри, что печатается, это поможет решить проблему". Это разные вещи. Ну, хорошо, если тебе лень самому посмотреть, я тебе покажу, что выведет твоя программа:

Summa funrcuu y=F1(x)/F2(x)
8.750000
8.510000
8.190000
7.790000
7.310000
6.750000
6.110000
5.390000
4.590000
3.710000
2.750000
1.710000
0.590000
-0.610000


, и после этого будет "Биг бада бум". Почему - еще не понятно? Потому что ты вызываешь Ln(отрицательное_число). Этого делать нельзя. Это понятно, почему? А ведь написано в FAQ-е ( http://forum.pascal.net.ru/index.php?s=&showtopic=4535&view=findpost&p=38227 ) :
Цитата
Способ x^a = Exp(a*Ln(x)) не подходит, т.к. для вычисления по этой формуле основание степени x должно быть положительным


Придется тебе возводить в степень по другому...

Автор: Mambakremen 13.11.2010 16:09

Ребята, извините, не знаю как по другому... ypriamii.gif
Какие ещё способы?
Из FAQ не пойму этих строк...

Код
Function minusOnePower(n: Integer): Integer;
  Begin
    minusOnePower := (1 - 2*Byte(Odd(n)));
  End;

Автор: TarasBer 13.11.2010 16:16

> Из FAQ не пойму этих строк...

F1 нажми, там всё написано и про функцию Odd и про приведение к byte
Только вот в какой-то версии ФПЦ разве True не приведётся к 255?

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

Автор: volvo 13.11.2010 16:31

У нас не FAQ по FPC. Огромное количество программ оттуда в FPC вообще не компилируются.

Это было первое. Второе: Mambakremen, каким боком тебе вообще нужна функция minusOnePower? Она возводит минус единицу в степень, тебе надо возвести отрицательное число в степень. Разницу видишь?

Ну, хорошо, совсем на пальцах: у тебя есть число X, тебе его надо возвести в степень 1/A (извлечь корень). Твои действия? Не надо никаких программ, ты просто скажи, на словах, что будешь делать, если тебе надо извлечь корень четной степени из числа? Проверишь на отрицательность, так? Если число под корнем отрицательное - ошибка. Если положительное - то все прекрасно, возводишь в степень через Exp(a*Ln(x)).

А теперь - что будешь делать, если надо извлечь корень НЕчетной степени? Проверил число на отрицательность, оно отрицательное, дальше что? Ошибки-то нет, вся разница - в том, что тебе надо в случае корня нечетной степени запомнить знак числа, потом вычислить корень из его модуля, и результату присвоить знак исходного выражения: было число (-27), степень (1/3) -> число отрицательное, корень нечетной степени, запоминаем знак. Вычисляем (Abs(-27))1/3 = 3, и добавляем тот знак, который запомнили. Ответ = (-3). Что не так?

Теперь - что тебе делать. Надо написать функцию:

function GetNthRoot(X: real; Power: integer): real;
begin
{ А здесь - сделать все то, что было написано выше }
end;

, и при вычислениях вызывать эту функцию. За тебя этого делать я не буду. Нужно - пиши. Не нужно - лови RTE 207 дальше.

Автор: Mambakremen 13.11.2010 16:36

Спасибо smile.gif Буду пробовать.

Автор: volvo 13.11.2010 18:52

Цитата
Только вот в какой-то версии ФПЦ разве True не приведётся к 255?
Кстати, таки не приведется:

Цитата(rtl.pdf (стр. 1080))
37.9.144 Odd
Synopsis: Is a value odd or even ?
Declaration:
function odd(l: LongInt): Boolean
function odd(l: LongWord): Boolean
function odd(l: Int64): Boolean
function odd(l: QWord): Boolean

Visibility: default
Description: Odd returns True if X is odd, or False otherwise.

, то есть, как видишь, все варианты этой функции вернут именно значение типа Boolean. А теперь смотрим сюда:
Цитата(ref.pdf (стр.24))

Table 3.3: Boolean types
Name Size Ord(True)
Boolean 1 1
ByteBool 1 Any nonzero value
WordBool 2 Any nonzero value
LongBool 4 Any nonzero value

Что гарантирует: результат Ord(Boolean) будет либо 0, либо 1. А с какой стати приведение Byte(1) может дать 255 - непонятно совершенно.

Автор: Mambakremen 15.11.2010 3:10

Решил не мучатся с функцией, простой усл. оператор вот, что получилось.

writeln('Summa funrcuu y=F1(x)/F2(x)');
x:=a;
repeat
t:=(6*-x*x);
if t=0 then F1:=0
else if t<0 then F1:=-exp((1/5)*ln(abs(t)))
else F1:=exp((1/5)*ln(t));
F2:=sin(exp(2*x)*ln(x))-cos(x);
y:=y+(F1/F2);
x:=x+c;
until x>b;


Автор: volvo 15.11.2010 3:19

Неправда. Число в нулевой степени - не ноль, а единица. Это во-первых. Во-вторых, не надо вещественное число сравнивать с 0, лучше сделать так:

t := (6*x-x*x);

if t < 0 then F1 := - exp((1/5)*ln(abs(t)))
else
if t > 0 then F1 := exp((1/5)*ln(abs(t)))
else F1 := 1; { То, что не меньше и не больше 0 - есть сам ноль }


Автор: TarasBer 15.11.2010 15:01

Возводим не в нулевую степень, а в 1/5.
0^(1/5)=0
Ноль должен быть, всё правильно там написано.
И почему с нулём в данном случае нельзя сравнивать?

Автор: volvo 15.11.2010 15:17

Вещественное с нулем нельзя сравнивать НИКОГДА. Равно как и с другими вещественными числами. Только больше/меньше/не_равно. Я бы вообще запретил для вещественных типов операцию сравнения, по крайней мере сделал бы предупреждение при попытке применить операцию "=" к операндам таких типов. Количество глюков (причем, далеко не всегда безобидных) в программах резко бы поубавилось.

Цитата
всё правильно там написано.
В таком случае, это делается еще проще:

var Flag: Integer;

t := (6*x-x*x);
if t > 0 then flag := 1
else if t < 0 then flag := -1
else flag := 0;

F1 := Flag * exp((1/5)*ln(abs(t)));

Автор: TarasBer 15.11.2010 15:50

Что случится в этом примере из-за сравнения с нулём? Что плохого здесь может сделать случайно вылезший бит погрешности?