Начала Паскаля: формы операторов цикла, циклическая обработка целых и вещественных значений

Данная тема посвящена рассмотрению особенностей и приёмов использования операторов цикла while, repeat и for при решении простых задач целочисленной и вещественной арифметики.

Вот несколько бонусных задач

Вот несколько бонусных задач, которые я предлагаю в качестве затравки к этой теме.

Задача1. Задано натуральное N. Определить, является ли оно натуральной степенью числа 2. Если да, то указать эту степень.

Задача2. Дана входная последовательность трёхзначных в десятичной записи натуральных чисел, завершающаяся нулём. Определить, начинается ли каждое, начиная со второго, число этой последовательности с цифры, которой оканчивается предыдущее число.

Задача3. Даны натуральные числа M и N. Найти решения всех квадратных уравнений: A*X^2 + B*X - 1 =0, где A=1, 2, ..., M; B =1,2. ..., N.

Задача 1

  1. Program Z1;
  2.   var n,s,i:integer;
  3. begin
  4.   readln(n); s:=1; i:=0;
  5.   while s<n do
  6.   begin
  7.     i:=i+1;
  8.     s:=s*2;
  9.   end;
  10.   if s=n then writeln('2^',i)
  11.   else writeln('Данное число не является степенью двойки');
  12. end.

1

  1. program stepen2ki;
  2.    var a,b,c:word;
  3. begin
  4.    readln(a);
  5.    b:=2;
  6.    c:=1;
  7.      while b<a do begin
  8.       c:=c+1;
  9.       b:=b*2;
  10.       end;
  11.    if b=a then writeln('yavlyaetsya',c:5,'oi stepen`y chisla 2')
  12.              else write ('ne yavlyaetsya stepen`y chisla 2');
  13.    readln
  14. end.

Задача 2

  1. Program Z2;
  2.   var
  3.   n,m:integer;
  4.   f:boolean;
  5. begin
  6.   readln(n); f:=false;
  7.   repeat
  8.     readln(m);
  9.     if (m div 100)<>(n mod 10) then f:=true;
  10.     n:=m;
  11.   until m=0;
  12.   if f=false then writeln('Условия задачи выполнены')
  13.   else writeln('Условия задачи не выполнены');
  14. end.

задача 3

  1. program uravneniya1;
  2.    var x,d,x1,x2:real; m,a,b,n:word;
  3. begin
  4.    readln(m,n,x);
  5.    for a:=1 to m do begin
  6.                      for b:=1 to n do begin
  7.                      d:=sqr(b)-4*a*(-1);
  8.                      if d>=0 then
  9.                              x1:=(-b-sqrt(d))/(2*a);
  10.                              x2:=(-b+sqrt(d))/(2*a);
  11.                              writeln('x1=',x1:2:3,' x2=',x2:2:3)
  12.                      end;
  13.                     end;
  14. readln
  15. end.

там есть вариант когда один

там есть вариант когда один корень смотри...
Program korni;
var
a,b,d,x:real;
m,n:Integer;
begin
writeln('введите A,B,');
readln( a,b);
writeln('введите m,n,');
readln( m,n);
for a:=1 to m do begin
for b:=1 to n do begin
d:=sqr(b)-4*a*(-1);
if d<0 then begin
writeln('действительных корней нет');
end;
else if d=0 then begin
x:=(-b)/2*a;
writeln('корень уравнения: ',x);
end else begin
x:=(-b+sqrt(d))/2*a;
writeln('корни уравнения: ',x);
x:=(-b-sqrt(d))/2*a;
writeln(' корни уравнения: ',x);
end

что то у меня не получается оформить правильно программу

подскажите кто-нибудь как

подскажите кто-нибудь как правильно оформлять программу?

Мария,если внимательно

Мария,если внимательно посмотреть на данное выражение A*x^2+B*x-1=0, то можно сделать вывод,что его дискриминант никогда не будет отрицательным,более того,он так же не будет равным 0, т.к B и A исходя из последовательности всегда положительные,а C(т.е. -1) нам уже дано,поэтому дискриминант будет состоять из числа равного положительное +положительное,а оно всегда больше нуля....
думаю Валерий Шахамболетович этим упростил нам задачу

3 задача

  1. Program korni;
  2. var
  3.    a,b,d,x:real;
  4.    m,n:Integer;
  5. begin
  6.    writeln('введите A,B,');
  7.    readln( a,b);
  8.    writeln('введите m,n,');
  9.    readln( m,n);
  10. for a:=1 to m do begin
  11. for b:=1 to n do begin
  12.     d:=sqr(b)-4*a*(-1);
  13.        if d<0 then begin
  14. writeln('действительных корней нет');
  15. end;
  16.        else if d=0 then begin
  17. x:=(-b)/2*a;
  18.       writeln(' единственный корень уравнения: ',x)
  19.        else begin
  20. x:=(-b+sqrt(d))/2*a;
  21.         writeln( '1-ый корень уравнения: ',x);
  22. x:=(-b-sqrt(d))/2*a;
  23.        writeln(' 2-й корень уравнения: ',x);
  24. end;
  25. end.
  26. <pre/>

Мария,если я правильно

Мария,если я правильно понял,то вы интересуетесь тем,как выделить програмный код в посте....
для этого вначале кода впишите <пре>,а в конце <пре/> (только пре латинскими буквами,т.е pre)

Валерию

ну я так решила,посмотреть хочу как все же рациональней будет писать программы,Спасибо=)

Тогда в Вашем решении можно

Тогда в Вашем решении можно было бы убрать 8-ю строчку, т.е. проверку на неотрицательность d

Наталия,да

Наталия,да действительно,просто я увидел что дискриминант всегда больше 0 только в ходе решения задачи и забыл убрать условие,спасибо за поправку

3

  1. program uravneniya1;
  2.    var x,d,x1,x2:real; m,a,b,n:word;
  3. begin
  4.    readln(m,n,x);
  5.    for a:=1 to m do begin
  6.                      for b:=1 to n do begin
  7.                      d:=sqr(b)-4*a*(-1);
  8.                      x1:=(-b-sqrt(d))/(2*a);
  9.                      x2:=(-b+sqrt(d))/(2*a);
  10.                      writeln('x1=',x1:2:3,' x2=',x2:2:3)
  11.                      end;
  12.                     end;
  13. readln
  14. end.

Валерий,Наталья,можно узнать

Валерий,Наталья,можно узнать вы сколько по времени паскаль изучаете???я вот стараюсь,сижу разбираюсь и у меня не все получается решать так быстро и рационально как это делаете вы???может поделетись секретом?

А первую задачу можно проще

А первую задачу можно проще решить...

Мария,признаюсь честно,я до

Мария,признаюсь честно,я до университета паскаль в 'глаза' не видел и никогда не занимался в спецшколах(т.е,например,турбо и др).Там где я учился,на информатике занимаются в бейсике,и то,я предполагаю,хотя точно не знаю,на среднешкольном уровне...В первые дни учебы,когда начинали писать программы на паскале я совершенно не знал что за var или например другие команды...Потом за короткое время начал вникать и стал понимать что это...
Поэтому паскаль я изучаю 2 месяца:)

Главное, старайся дальше, и

Главное, старайся дальше, и все у тебя получится. Чем больше думаешь, тем становишься умней :)

..

Поддерживаю Наталию:)

Зад.1.

предположу такое к зад.1:

  1. program z1;
  2. var g,a,m:integer;
  3. begin
  4. readln(n);
  5. if g:=n/2=0 then
  6. a:=n div 2;
  7. writeln(a);
  8. end.

Она не до конца работает просто хочу понять "в ту сторону думаю". Если да, можете объяснить почему в цикле if пишет "Boolean expected".

Ну во-первых m ты перепутал с

Ну во-первых m ты перепутал с n(описал m,а использовал n),во-вторых непонятно g:=n/2=0

После If должно стоять

После If должно стоять булевское значение, поэтому возникает такая ошибка

Может что-то так? Вообще идея

1 Программа
Может что-то так?
Вообще идея с div верна?
И наверно там ещё нужен цикл? Кстати там ещё наверно n>=0.
Если совсем не правильно, то умываю руки. Т.к. не хочу разводить конференцию целую.

Вы сами понимаете, что нужен

Вы сами понимаете, что нужен цикл. Зачем писать заведомо неверные программы? У Вас получается, что любое число большее нуля является двойкой в некоторой степени.
6 div 2 тоже равно 0, но 6 не является двойкой в степени. Нужно как-то это учесть.

Comment к бонусным задачам ...

1. Первую задачу действительно можно решить иначе. Не знаю, проще ли, но сделать быстрее - точно можно. Интересно, Наташа, какое решение имеете в виду Вы (пришлите на почту).

2. Решение второй задачи (представлено Алексеем Зубко) содержит ошибку. Найдите.

3. С третьей задачей, в конце концов (не без помощи той же Натальи), справились почти как надо (есть-таки маленький изъян!). А вот над формой вывода решений я бы здесь поработал.

Замечание. Конечно, главные лавры в этой бонусной сессии достались двоим, одним из немногих наиболее активных - Алексею и Валерию.
Но, прошу обратить внимание(!). Во-первых, на время публикации условий задач , во-вторых, на время представления последних вариантов решений и, в-третьих, на то, что до сих пор (а сейчас уже вечер) задачи нельзя считать закрытыми полностью и комментарии к их решению принимаются.

Это я пишу для тех, кто считает, что вовремя успеть (решить, обсудить, поучаствовать) и заработать бонус невозможно. Соглашусь, что действительно не возможно ... если не заходить на сайт!

Роман...

Кроме банального "возьмите лекции - там обо всём написано" (в частности, о том, чем выражение отличается от оператора, как устроен оператор if, что такое булевское выражение и какова его структура, чем отличается вещественная арифметика от целочисленной) увы, ничего посоветовать не могу.

Ну, я имею ввиду Ваше

Ну, я имею ввиду Ваше решение, Вы мне его в прошлом году показали. Оно мне на столько понравилось, показалось изящным и простым, что я его до сих пор помню. Уж не знаю, когда забуду :))

Ошибка в решении Алексеем второй задачи

В его решении проверяется последнее число последовательности, которое у нас всегда ноль(условие выхода). Вот изменённый вариант решения:

  1. Program Z2;
  2.   var
  3.   n,m:integer;
  4.   f:boolean;
  5. begin
  6.   readln(n); f:=false;
  7.   repeat
  8.     readln(m);
  9.     if((m div 100)<>(n mod 10))and(m<>0) then f:=true;
  10.     n:=m;
  11.   until m=0;
  12.   if f=false then writeln('Условия задачи выполнены')
  13.   else writeln('Условия задачи не выполнены');
  14. end.

Не помню, Наташа,

Не помню, Наташа, чтобы эту задачу (1) решал, тем более, как-то по особенному. Ну, так покажите же мне моё решение!

ОК, Сергей, ошибку нашли и

ОК, Сергей, ошибку нашли и исправили.
Но вот решение в целом получилось не очень изящным...

ОП, фэйл... Сергей, жаль что

ОП, фэйл...
Сергей, жаль что не забрёл сюда проверить обстановку раньше вас. ) Но... Спасибо за указание!

Валерий Шахамболетович...Я

Валерий Шахамболетович...Я вобще-то Сергей:) А решение ну лично я бы while..do решал бы...Но вопрос то стоял найти ошибку в его алгоритме..

Извините, Сергей, делаю сразу

Извините, Сергей, делаю сразу три дела. Я сам заметил и уже исправил.
А по поводу качества кода - тоже не обессудьте, я эстет.

Ну, для Вас может и не

Ну, для Вас может и не по-особенному, а для меня образец, как нужно делать:

  1. Readln(n);
  2. while (n mod 2 = 0) do
  3.    n := n div 2;
  4. if (n = 1) then
  5.    Writeln('Yes')
  6. else
  7.    Writeln('No')

Спасибо, Наташа. Это решение

Спасибо, Наташа. Это решение мне действительно кажется наиболее естественным. Хотя, оно и не сильно отличается от предложенного ребятами.
Единственно, если уж очень критична эффективность, то в этом своём решении, я бы подправил цикл:

  1. while not odd(n) do
  2.    n := n shr 1;

И всё же, не увидел я решения

И всё же, не увидел я других решений задачи 2. Осмелюсь предложить:

  1. Program Z2;
  2.   var Left, Right: Word;
  3.         flag: Boolean;
  4. Begin
  5.    Readln(Left);
  6.    repeat
  7.       Readln(Right);
  8.       flag:= (Left mod 10)=(Right div 100);//в правой части  бул. выражение
  9.       If not flag Then break; //завершаем, возможно, досрочно
  10.       Left:=Right
  11.   until  Right=0;
  12.   If Right =0 then Writeln('Yes')
  13.   else Writeln('No')
  14. End.

Или так:

  1. ...
  2.   Readln(Left); Right:=1; flag:=true;
  3.   While flag and (Right<>0) do begin
  4.       Readln(Right);
  5.       flag:= (Left mod 10)=(Right div 100);//в правой части бул. выражение
  6.       Left:=Right
  7.   End;
  8.   If Right =0 then Writeln('Yes')
  9.   else Writeln('No')
  10. ...

Думайте как программисты!

Думайте как программисты - процессами (т.е. во времени!), а не как математики - формулами. Вторая, исправленная версия решения задачи 3 в исполнении Баланко В. (первая версия не просто неэффективна, но и содержит ошибку. Какую?) может быть уcкорена так:

  1. ...
  2.  for a:=1 to m do begin
  3.         a1:=2*a;
  4.          for b:=1 to n do begin
  5.                      d:=sqr(b) + 2*a1;
  6.                      b1:= -b/a1;
  7.                      sq:=sqrt(d)/a1;
  8.                      x1:= b1+sq;
  9.                      x2:= b1-sq;
  10.                      writeln('x1=',x1:10:3,' x2=',x2:10:3)
  11.          end
  12.  end;
  13. ...

С учётом того, что изменения внесены в тело цикла и ещё того, что cтандартная функция sqrt(X) в её внутренней реализации (например, по формуле Ньютона) сама по себе требует циклических вычислений плавающей точки, как вы думаете, много ли мы выиграли?