помогите с задачей

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Re: помогите с задачей

Сообщение xoma » 21.12.2012 16:57:00

Но даже после исправления всех синтаксических ошибок, логические останутся на месте.
Ваши результаты: Q(1.4) = 2.586, Q(-2) = 10.816, Q(2) = 1.187
Берём куркулятор, считаем Q(1.4) = 1.65 * 1.4^3 + 7 * √1.4 = 4.5276 + 8.2825 = 12.810.
Не сходится, однако. Согласны?

да((
код я в ручную набирала,а не копировала, может где то ошибку и сделала
Q при x = 1.4 у меня ровняется 1,134,но все равно явная ошибка((

Добавлено спустя 1 час 34 минуты 23 секунды:
[quote="bormant"Но даже после исправления всех синтаксических ошибок, логические останутся на месте.
Ваши результаты: Q(1.4) = 2.586, Q(-2) = 10.816, Q(2) = 1.187
Берём куркулятор, считаем Q(1.4) = 1.65 * 1.4^3 + 7 * √1.4 = 4.5276 + 8.2825 = 12.810.
Не сходится, однако. Согласны?[/quote]
согласна,буду читать..
скажите,а почему вы брали именно 1е-7?
xoma
незнакомец
 
Сообщения: 9
Зарегистрирован: 19.12.2012 18:41:10

Re: помогите с задачей

Сообщение bormant » 21.12.2012 20:40:24

В худшем случае (single):
Код: Выделить всё
type
  real_t = single;

var
  x, y, z: real_t;

begin
  x := 1.4;
  y := 1;
  while x+y > x do begin
    z := y;
    y := y / 10;
  end;
  writeln(z);
end.
Прогон:
Код: Выделить всё
0.999999870E-07
то есть, 1*10^7 или в научной записи 1e-7. Если это число поделить на 10, то прибавление результата к 1.4 уже не изменит значение, остаётся всё равно 1.4. Можно посчитать предел точности ещё аккуратнее, если делить не на 10, а на 2, но практического смысла в этом нет:
Код: Выделить всё
5.960464478E-08
Для другого действительного числа того же типа предел точности будет иной, зависит в первую очередь от порядка. Так получается из-за того, что мантисса, дающая сколько-то значащих цифр, и порядок числа хранятся отдельно.
Для других действительных типов пределы точности для 1.4 будут соответственно:
Код: Выделить всё
double: 1e-15
extended: 1e-19
Для Real из Turbo Pascal от Borland не скажу, нет под рукой компилятора.
Подробнее:
http://ru.wikipedia.org/wiki/%D0%9F%D0% ... 0%B0%D1%8F
http://ru.wikipedia.org/wiki/IEEE_754-2008
и по ссылкам оттуда.
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: помогите с задачей

Сообщение xoma » 21.12.2012 21:33:01

я поняла, погрешность..
а если без нее делать?
вот и результаты с обычным решение совпадают(как вы говорили при х = 1,4, 2 и -2)
Код: Выделить всё
program zad1_var4;
uses crt;
const
a=1.65;
b=1.4;
var
x, q: real;
  begin
  clrscr;
  writeln ('      Kontrol. rabota 1, varian 4');
  writeln ('     ---------------, shifr ------------');
  writeln ('      a= ',a:4:2);
  write ('Vvedite x = '); readln(x);
   if x < b  then q:=pi*sqr(x)-7/sqr(x) else
    if x = b then q:=a*(x*x*x)+7*sqrt(x)
     else q:=ln(x+7*sqrt(abs(x+a)))/ln(10);
    writeln ('Q= ',q:7:4);
    writeln ('------');
    readln;
end.
xoma
незнакомец
 
Сообщения: 9
Зарегистрирован: 19.12.2012 18:41:10

Re: помогите с задачей

Сообщение bormant » 22.12.2012 11:59:12

xoma писал(а):вот и результаты с обычным решение совпадают(как вы говорили при х = 1,4, 2 и -2)

Сходил на сайт Embarcadero в музей, скачал Turbo Pascal 5.5, рассказываю...
Модифицируем программку так, чтобы явно выводилась выбранная ветка вычислений, например:
Код: Выделить всё
const
  a = 1.65;
  b = 1.4;
var
  x: real;
begin
  write('x = '); readln(x);
  if x < b then
    writeln('x < ', b:0:1, ', Q(', x:0, ') = ', pi * sqr(x) - 7 / sqr(x):0:4)
  else if x = b then
    writeln('x = ', b:0:1, ', Q(', x:0, ') = ', a * sqr(x) * x + 7 * sqrt(x):0:4)
  else
    writeln('x > ', b:0:1, ', Q(', x:0, ') = ', ln(x + 7 * sqrt(abs(x + a))) / ln(10):0:4);
end.
Прогон 1:
Код: Выделить всё
x = 1.4
x = 1.4, Q( 1.4E+00) = 12.8101
А теперь несколько изменим настройки компиляции, в настройках среды включим использование математического сопроцессора или передадим соответствующий параметр компилятору (а можно добавить в начале программы директиву {$N+}, делающую то же самое).
Прогон 2:
Код: Выделить всё
x = 1.4
x < 1.4, Q( 1.4E+0000) = 2.5861
Одна и та же программа повела себя по-разному. Во втором случае введённое с клавиатуры 1.4 меньше 1.4, использованного внутри программы ;-) При b=1.6 было бы больше, а при b=1.5 работоспособность сохранилась бы, поскольку 1.5 имеет точное представление в формате IEEE-754.
В чём же дело? Во времена процессоров 8080, 8086, 80286, 80386 математический сопроцессор был штукой относительно редкой, поэтому в состав Turbo/Borland Pascal включена библиотека, программно реализующая работу с вещественной арифметикой средствами центрального процессора, естественно, существенно медленнее аппаратного решения. Её разработчики учли неминуемые погрешности при вычислении. Начиная с 486 ситуация стала противоположной, математический сопроцессор встроили в CPU (да, продавались 486sx, но это всего лишь брак -- годный CPU с нерабочим сопроцессором). А вот мат.сопроцессоры ещё со времён 8087 считают как показано во втором прогоне.

Если правильно путаю, в Free Pascal получить результаты как в прогоне 1 не удастся, поскольку возможность действительной арифметики без использования сопроцессора отсутствует. Поэтому, если работу вашей программы будут проверять при помощи FPC, верного результата не получится. Изменения, как уже говорил, минимальны:
Код: Выделить всё
const
  eps = 1e-7;
  a = 1.65;
  b = 1.4;
var
  x: real;
begin
  write('x = '); readln(x);
  if abs(x - b) < eps then
    writeln('x = ', b:0:1, ', Q(', x:0, ') = ', a * sqr(x) * x + 7 * sqrt(x):0:4)
  else if x < b then
    writeln('x < ', b:0:1, ', Q(', x:0, ') = ', pi * sqr(x) - 7 / sqr(x):0:4)
  else
    writeln('x > ', b:0:1, ', Q(', x:0, ') = ', ln(x + 7 * sqrt(abs(x + a))) / ln(10):0:4);
end.
Обратите внимание на перенос условия проверки на равенство в начало -- это делать обязательно, иначе стоящее ранее условие x < 1.4 сработает (помните прогон 2, введённое 1.4 было меньше) и до проверки на равенство дело не дойдёт.
Формат вывода :0:4 заставит использовать 4 знака под дробную часть, а под целую часть: 1 позиция на знак числа плюс столько позиций, сколько нужно для правильного отображения целой части. Это число тоже можно вынести в константы для гибкого управления выводом, например,
Код: Выделить всё
const
  eps = 1e-7; prec = 3;
  a = 1.65; b = 1.4;
var
  x: real;
begin
  write('x = '); readln(x);
  if abs(x - b) < eps then
    writeln('x = ', b:0:1, ', Q(', x:0, ') = ', a * sqr(x) * x + 7 * sqrt(x):0:prec)
  else if x < b then
    writeln('x < ', b:0:1, ', Q(', x:0, ') = ', pi * sqr(x) - 7 / sqr(x):0:prec)
  else
    writeln('x > ', b:0:1, ', Q(', x:0, ') = ', ln(x + 7 * sqrt(abs(x + a))) / ln(10):0:prec);
end.
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: помогите с задачей

Сообщение Vapaamies » 22.12.2012 16:53:15

bormant писал(а):в Free Pascal получить результаты как в прогоне 1 не удастся, поскольку возможность действительной арифметики без использования сопроцессора отсутствует.

Похоже, что в нем все же есть тип Real48 (по аналогии с Delphi), о котором я писал в теме вычитки "Песен о Паскале".
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: помогите с задачей

Сообщение xoma » 22.12.2012 21:48:42

bormant писал(а):
xoma писал(а):

спасибище :)
xoma
незнакомец
 
Сообщения: 9
Зарегистрирован: 19.12.2012 18:41:10

Re: помогите с задачей

Сообщение bormant » 22.12.2012 22:00:48

Vapaamies писал(а):Похоже, что в нем все же есть тип Real48 (по аналогии с Delphi), о котором я писал в теме вычитки "Песен о Паскале".
Только от того, что он есть, ни холодно, ни жарко, сами же ссылку дали, а по ней недвусмысленно значится:
Код: Выделить всё
type
  real48 = array [0..5] of Byte;
Последствия подобной декларации вполне ожидаемы:
Код: Выделить всё
type
  real_t = Real48;
var
  x, y, z: real_t;
begin
  x := 1.4; y := 1;
  while x+y > x do begin
    z := y; y := y / 10;
  end;
  writeln(z);
end.
Код: Выделить всё
Compiling task.pas
task.pas(6,8) Error: Incompatible types: got "Extended" expected "real48"
task.pas(6,18) Error: Incompatible types: got "ShortInt" expected "real48"
task.pas(7,10) Error: Operator is not overloaded: "real48" + "real48"
task.pas(8,20) Error: Operator is not overloaded: "real48" / "ShortInt"
task.pas(10,12) Error: Can't read or write variables of this type
task.pas(12) Fatal: There were 5 errors compiling module, stopping
Fatal: Compilation aborted
То есть тип-то есть, по хранению совместим с Turbo/Borland Pascal-евским Real, а вот арифметика для него не определена.
Единственное, что можно с ним сделать -- преобразовать в Double/Extended:
http://www.freepascal.org/docs-html/rtl ... ouble.html
http://www.freepascal.org/docs-html/rtl ... ended.html
http://www.freepascal.org/docs-html/rtl ... ouble.html
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: помогите с задачей

Сообщение Vapaamies » 23.12.2012 12:16:38

bormant писал(а):[/code]Последствия подобной декларации вполне ожидаемы

Да, не обратил внимания, каюсь. Вообще, чем я больше читаю форум FreePascal.ru, тем больше нахожу оправданий, почему у меня так и не получилось писать на FreePascal. :lol:
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: помогите с задачей

Сообщение xoma » 30.12.2012 01:51:29

4 задача.jpg
(zad4)Задана функция в полярных координатах при . Используя оператор цикла рассчитать и отпечатать таблицу функции при , меняющемся в интервале с шагом .
4 задача.jpg (8.85 КБ) Просмотров: 10231
3 задача.jpg
(zad3)составить программу типа «цикл в цикле» для расчета и печати двух таблиц значений указанной функции при A=1,1 и А=1,6.
3 задача.jpg (8.25 КБ) Просмотров: 10231
посмотрите еще 2 задачки plz
Код: Выделить всё
program zad3_var3;
uses crt;
var
  a, b, x, y: real;

   begin clrscr;

   a:=1.1;
   while a<1.61 do

    begin
    writeln('   a=  ',a:3:1);
    writeln('------------------------------');
    x:=0.5;
    while x<5.1 do

     begin
     b:=1+a*x;
     y:=(sqr(ln(b)))/b;
     writeln('   x=  ',x:7:3,'   y=  ',y:7:3);
     x:=x+0.5;
     end;

    a:=a+0.5;
    end;

   writeln;
   readkey;
   readln;
   end.

Код: Выделить всё
program zad4_var4;
uses crt;
const
a=4;
var
i: integer;

rad, grad, r: real;

    begin clrscr;
    rad:=0;
    for i:= 1 to 17 do
    begin
    grad:= rad * (180/pi);
r:= a*(sin(2*grad)+cos(2*grad));
writeln('   rad=   ',rad:1:2,'   grad=   ',grad:1:1,'   r=   ',r:1:2);
rad:= rad+pi/8;


readln;
  end;
end.


Добавлено спустя 3 минуты 56 секунд:
xoma писал(а):
4 задача.jpg
(zad4)Задана функция в полярных координатах при . Используя оператор цикла рассчитать и отпечатать таблицу функции при , меняющемся в интервале с шагом .
4 задача.jpg (8.85 КБ) Просмотров: 10231
3 задача.jpg
(zad3)составить программу типа «цикл в цикле» для расчета и печати двух таблиц значений указанной функции при A=1,1 и А=1,6.
3 задача.jpg (8.25 КБ) Просмотров: 10231
посмотрите еще 2 задачки plz
Код: Выделить всё
program zad3_var3;
uses crt;
var
  a, b, x, y: real;

   begin clrscr;

   a:=1.1;
   while a<1.61 do

    begin
    writeln('   a=  ',a:3:1);
    writeln('------------------------------');
    x:=0.5;
    while x<5.1 do

     begin
     b:=1+a*x;
     y:=(sqr(ln(b)))/b;
     writeln('   x=  ',x:7:3,'   y=  ',y:7:3);
     x:=x+0.5;
     end;

    a:=a+0.5;
    end;

   writeln;
   readkey;
   readln;
   end.

Код: Выделить всё
program zad4_var4;
uses crt;
const
a=4;
var
i: integer;

rad, grad, r: real;

    begin clrscr;
    rad:=0;
    for i:= 1 to 17 do
    begin
    grad:= rad * (180/pi);
r:= a*(sin(2*grad)+cos(2*grad));
writeln('   rad=   ',rad:1:2,'   grad=   ',grad:1:1,'   r=   ',r:1:2);
rad:= rad+pi/8;


readln;
  end;
end.

условие к zad4
Вложения
Безымянный.jpg
xoma
незнакомец
 
Сообщения: 9
Зарегистрирован: 19.12.2012 18:41:10

Пред.

Вернуться в Обучение Free Pascal

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

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

Рейтинг@Mail.ru