Персональная страничка
Диканева Тараса
Викторовича

Главная \ Преподавательское \ Программирование для начинающих

1. Линейные программы: арифметические операторы, стандартные функции и ввод/вывод в текстовом режиме

Предыдущий раздел:

Следующий раздел:

1.7. Задачи на составление арифметических выражений

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

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

В данном случае мы имеем дело с простейшей ситуацией – по сути, требуется придумать программу, состоящую из одной строки. Набор операций дан, требуется их скомбинировать так, чтобы получился требуемый результат. Решение данных задач позволит выработать правильный подход и настрой для работы в ситуации когда «неизвестно что делать».

Задания:

Используя арифметические операторы (+, -, *, /, div, mod), а также функции round(), trunc() и abs(), составьте арифметические выражения для вычисления следующих величин:

1. n-е четное число (первым считается 2, вторым 4 и т.д.)

2. n-е нечетное число (первое равно 1, второе 3 и т.д.)

3. В очереди стоят n людей, сколько человек находится между i-м и k-м в очереди.

4. Сколько нечетных чисел на отрезке (a, b), если a и b – четные? Если a и b – нечетные? a –четное, b – нечетное?

5. Сколько полных минут и часов содержится в x секундах?

6. В доме 9 этажей, на каждом этаже одного подъезда по 4 квартиры. В каком подъезде, и на каком этаже находится n-я квартира.

7. Старинными русскими денежными единицами являются: 1 рубль – 100 копеек, 1 гривна — 10 копеек, 1 алтын — 3 копейки, 1 полушка — 0,25 копейки. Имеется А копеек. Запишите выражения для представления имеющейся суммы в рублях, гривнах, алтынах и полушках.

8. Стрелка прибора вращается с постоянной скоростью, совершая w оборотов в секунду (не обязательно стрелка прибора, может быть это волчок в игре «Что? Где? Когда?» и т.п.) Угол поворота стрелки в нулевой момент времени примем за 0. Каков будет угол поворота через t секунд?

9. Вы стоите на краю дороги и от вас до ближайшего фонарного столба x метров. Расстояние между столбами y метров. На каком расстоянии от вас находится n-й столб?

10. Та же ситуация, что и в предыдущей задаче. Длина вашего шага z метров. Мимо скольких столбов вы пройдете, сделав n шагов.

11. x – вещественное число. Запишите выражение, позволяющее выделить его дробную часть.

12. x – вещественное число. Запишите выражение, которое округлит его до сотых долей (останется только два знака после запятой).

13. n – целое число. Запишите выражение, позволяющее узнать его последнюю цифру.

14. n – четырехзначное целое число. Запишите выражение, позволяющее узнать его первую цифру.

15. Оператор div в Паскале работает только для целых чисел. Составьте выражение, позволяющее получать целую часть от деления вещественных чисел.

16. Выразите операцию mod через другие арифметические операции.

17. x – вещественное число. Запишите выражение, которое даст +1, если x>0 и -1, если x<0 (при x=0 выражение будет неопределено).

18. n и m – целые числа. Запишите выражение, которое давало бы 0, если n кратно m и 1, если не кратно.

19. От бревна длиной L отпиливают куски длиной x. Сколько кусков максимально удастся отпилить.

20. Бревно длиной L распилили в n местах. Какова средняя длина получившихся кусков?

21. Резиновое кольцо диаметром d разрезали в n местах. Какова средняя длина получившихся кусков?

22. На прямой через равные промежутки располагается n точек. Расстояние от первой до последней равно L. Чему равно расстояние от первой точки до i-й? А от k-й до последней? А от i-й до k-й?

23. Известно, что приближенные формулы для вычисления синуса и косинуса работают тем точнее, чем меньше значение аргумента. Поскольку синус и косинус 2π-периодические функции (sin(x) = sin(x+2πn) , где n – любое целое число), то можно вычисление синуса от любого аргумента привести к вычислению синуса от аргумента, лежащего в диапазоне от 0 до 2π. Запишите формулы, позволяющие:
(а) привести положительный угол x в диапазон от 0 до 2π.
(б) аналогично для отрицательного угла.

24. Пусть дано трехзначное число x (например, 123). Составьте выражения, которые позволят вычислить первую, вторую и третью цифру этого числа (числа 1, 2 и 3 в примере). Для облегчения поиска решения имейте в виду, что для двузначного числа первая цифра дается выражением

  d1:=x div 10;

а вторая выражением

  d2:=x mod 10;

Следующий раздел:

Предыдущий раздел:

327 комментариев

  1. Артур

    Алексей, решается очень легко. Подумай с функцией модуля))) если не получится, пиши, подскажу)

  2. Taras

    Я снова с вами! Но, кажется, вы тут и без меня разобрались ))

    Знак «<» воспринимается как начало HTML-тега (их можно использовать в комментариях). Из-за этого проблемы. Попробую на днях с этим справиться.

  3. Алексей

    Артур, спасибо за наводку. Действительно просто, а я искал какое-то заумное решение))

  4. Алексей

    а 18 не подскажешь?))

  5. Артур

    Тарас Викторович! Куда пропадали-то?))))))
    а у меня как всегда глупые проблемы… С Компилятора копирую код, и вставляю в блокнот, в ворд,или сюда, и все что написано по русски всякими каракулями…. Англ норм, а русские буквы капец.

  6. Артур

    Алексей, я 18 еще не решал, извини, сейчас не могу так как компилятора нет под рукой и бошка уже не варит, завтра подумаю и напишу))))
    17ое у меня в две строчки решение и с одной переменной, у тебя так же?

  7. Алексей

    ок)) а по 17 x:= abs(x)/x, почему две строчки?

  8. Алексей

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

  9. Артур

    Var
    x: real;
    Begin
    readln(x);
    writeln(x+(abs(x)/x));
    readln
    end.

  10. Артур

    блин… Или не требуется, чтобы прибавилось\отнялось к введенному числу? Просто чтоб отразилось +1 или — 1))) я условие походу чуток не понял

  11. Taras

    >> Куда пропадали-то?))))))

    Догуливал не израсходованный летом отпуск ))

    >> С Компилятора копирую код, и вставляю в блокнот, в ворд,или сюда, и все что написано по русски всякими каракулями…

    Во Free pascal используется древняя DOS’овская кодировка. Когда открываешь pas-файл в Word он по-идее должен спросить, в какой кодировке его открывать — выбирай DOS, а не Windows. Еще можно поискать текстовый редактор с автоопределнием кодировок. Такие есть.

    В 17-й должна получаться единица или минус единица, как у Алексея.

    А 18-я задача оказалась чуть сложнее прочих. Есть о чем подумать ))

  12. Артур

    Спасибо))) 18 вообще интересно… все равно догадаюсь, не подсказывайте))))

  13. Алексей

    о, а я уже хотел выкладывать её решение)). Я так понимаю, что если n<m, то должна отобразиться 1?

  14. Taras

    Да, это частный случай некратности.

  15. Артур

    Ну блин я уже вообще… Намекните мне, пожалуйста (только без решения)

    У меня мысль вот такая:
    (m mod n)/(…..)
    тоесть вот если в первой скобке остаток 0, то во второй уже не важно что, и выводится 0. Когда же в первой скобке какое-то число получается, то нужно во второй скобке что-то придумать, чтоб при делении или умножении на нее получилась 1….

    Сначала я вообще с лёту написал (m mod n) div (m mod n), когда n не кратно m — все отлично… а когда кратно, НА НОЛЬ ДЕЛИТЬ НЕЛЬЗЯ(( думаю-думаю какое выражение придумать во вторую скобку..никак.. и может я вообще неправильно думаю?

  16. Артур

    Я же, надеюсь, не путаю кратные. Правильно говорить, например, 4 кратно 4,8,12 … и тд. а не наоборот же — 8 кратно четырем и двум? Просто я в инете смотрел о кратных, везде по разному пишут, запутали меня.. я всегда знал, что число имеет бесконечное количество кратных. И заданному числу кратны числа, которые без остатка делятся на заданное число, ну и они разумеется должны быть >= заданного числа.
    и в нашем же случае, если говорится, что n кратно m, должно быть m>=n ???

  17. Taras

    Большее число кратно меньшему (уточнял по классическому справочнику по элементарной математике Выгодского). Но для придумывания решения это не так уж и важно. Если получается наоборот — 1 для кратности и 0 для некратности, то придумать выражение, которое из нуля сделает единицу, а из единицы ноль — не проблема.

    Ну, а в качестве намека. Один из вариантов решения:
    — получить отрицательное значение в случае кратности и положительное в случае некратности.
    — решением 17-й задачи сделать из них -1 или 1.
    — и, наконец, преобразовать их в 0 или 1.

    Есть и другие варианты.

  18. Артур

    ааааа неужели до меня дошло! зациклился на одном и ничего не получалось. Спасибо, Тарас Викторович, за намек! Только у меня вопрос, как всегда… сначала я написал вот такое:
    Program vosemnadcatoe_zadanie;
    Var
    m, n, z: integer;
    Begin
    readln(n);
    readln(m);
    z:=(((abs((((m mod n)-(m+1)*(m mod n) )+(m mod n) )+1)div ((((m mod n)-(m+1)*(m mod n) )+(m mod n) )+1) )*(-1) )+1) div 2;
    writeln(z);
    readln
    end.

    потом выражение разбил на несколько по-меньше и написал комментарии:

    Program vosemnadcatoe_zadanie;
    Var
    m, n, o, x, y, z: longint;
    Begin
    writeln(‘Программа проверит кратность введенных Вами числел, и выдаст 0, если n кратно m, и 1, если n не кратно m.’);
    write(‘n = ‘);
    readln(n); // Ввод переменной.
    write(‘m = ‘);
    readln(m); // Ввод переменной.
    y:=m mod n; // Остаток от деления,
    x:=((y-(m+1)*y)+y)+1; // Из остатка отнимается в несколько раз большее самого остатка и прибавляется просто остаток,поэтому всегда при некратности будет отрицательное число. Далее прибавляется единица,чтобы избежать нуля при кратности.
    o:=(abs(x)) div (x*(-1))+1; // В данном выражении сначала получаем -1 при кратности и 1 при некратности. Затем прибавляем единицу, чтобы при кратности всегда получался 0, а некратности 2.
    z:=o div 2; // Предыдущее выражение делим на 2, таким образом при кратности все равно окажется ноль (0/2), а при некратности всегда единичка (2/2).
    write(‘Ответ: ‘);
    writeln(z); // Вывод ответа.
    readln
    end.

    И теперь вопросы:

    Если представить, что мы в прошлом веке и у нас соответствующие компы, какой код для компа легче, первый, где все решение в одной переменной, или второй, где решение разбито на несколько переменных? И какая программа будет меньше весить(не обращая внимания на комменты, представить, что их вообще нет в обоих кодах).

    Еще у меня одна странность. В первой программе, ввожу n=111 m=331, все путём-показывает 1, если же во второй программе ввести такие числа, с типом переменных integer, появляется ошибка! Поменял тип на longint и всё стало хорошо… В чём прикол я не пойму, цифры-то не большие! Да и алгоритм решения аналогичен первому и там с integer работает…

  19. Алексей

    Ого, какое длинное решение)) У меня немного короче вышло
    program zad18;

    var
    x,n,m: integer;

    begin
    write(‘Введите число n = ‘);
    readln(n);
    write(‘Введите число m = ‘);
    readln(m);
    x:= round((n mod m)/(n mod m+0.1));
    writeln( x );

    end.

  20. Артур

    Хм.. вообще у меня первая мысль тоже была сделать решение в двух скобках. НО, во вторую скобку нихрена придумать не мог. и, КСТАТИ, я счас твою задачу в компиллятор скопировал, что-то не работает..))) ввожу 2 и 4, показывает 1, а не ноль )

  21. Артур

    а… у тебя в скобках n и m поменять надо))))) да, у тебя короче гораздо)) я был близок к такому решению, но блин не доперло чуток)) ну..главное результат)))

  22. Taras

    Оба варианта интересны и для меня неожиданны ))
    Кстати,

    x:=((y-(m+1)*y)+y)+1;

    упрощается до

    x:=y*(1-m)+1;

    Мой вариант получения отрицательного числа в случае кратности был

    x := m mod n — 0.5;

    Еще для коллекции решений:

    x := trunc(m div n — m/n + 1);

    >>Если представить, что мы в прошлом веке и у нас соответствующие компы, какой код для компа легче, первый, где все решение в одной переменной, или второй, где решение разбито на несколько переменных? И какая программа будет меньше весить(не обращая внимания на комменты, представить, что их вообще нет в обоих кодах).

    В первом варианте ты 6 раз вычисляешь одно и то же выражение (n mod m). По-идее, это должно занять больше времени, чем использование однажды посчитанного. Правда, современные компиляторы достаточно умны. Есть шанс, что при переводе в машинные коды, компилятор упростит это выражение, убрав повторные вычисления. Но все же писать так — это немножко дурной тон.

    >>Еще у меня одна странность. В первой программе, ввожу n=111 m=331, все путём-показывает 1, если же во второй программе ввести такие числа, с типом переменных integer, появляется ошибка! Поменял тип на longint и всё стало хорошо… В чём прикол я не пойму, цифры-то не большие! Да и алгоритм решения аналогичен первому и там с integer работает…

    Промежуточное значение (m+1)*y оказывается равным 36188, что выходит за границы для типа integer (215-1 = 32767 — во Free Pascal). Почему работает первый вариант — загадка. Возможно, компилятор действительно как-то по-своему упростил выражение, так что больших промежуточных результатов не возникает.

  23. Артур

    Прикольно, одну задачку каждый решил по-своему))))
    Тарас Викторович, а не подскажите по поводу 11 задачи. Само решение простое.
    Program odinnadcatoe_zadanie;
    Var
    x: real;
    Begin
    readln(x);
    x:=x-trunc(x);
    writeln(x);
    readln
    end.

    Но вот в чем проблема…
    допустим вводишь число 7.689, он выдаст ответ не 0.689, а 6.89..почему он так издевается?
    можно дополнить оператор writeln, написав writeln(x:0:3), НО вещест.число может ведь иметь разное количество цифр после запятой…Решил количество десятичных цифр сделать переменной и как-нибудь придумать записать в эту переменную количество, как я только не изголялся. Сначала думал как-то математически, если считать цифры в целом числе, то все просто, цикл while и делишь на 10, пока не получится ноль. а тут же никак, запятую вправо переносить, умножая на 10, но черт его знает сколько нести… хотел перевести число в строку.. но ничего толкового не вышло…. может есть способ решения данной проблемы?

  24. Артур

    тоесть даже не 6.89, а 6.8900000000000Е-001 показывает, пока к оператору вывода не добавить колич.знакомест и колич. десятич. цифр…

  25. Артур

    Не подскажите, правильно я 21 решил?
    Program dvadcat_pervoe_zadanie;
    Var
    d, n: integer;
    c, x: real;

    Begin
    writeln(‘Программа покажет среднюю длинну отрезанных кусков от резинового кольца, если ввести диаметр кольца и количество разрезов, сделанных на кольце.’);
    writeln;
    write(‘Введите диаметр кольца: ‘);
    readln(d);
    writeln;
    write(‘Введите количество разрезов: ‘);
    readln(n);
    c:=Pi*d;
    x:=c/n;
    writeln;
    writeln(‘Ответ: ‘, x:0:2);
    readln
    end.

  26. Артур

    осталось мне решить последнюю задачу..23.. и незнаю как

  27. Taras

    6.8900000000000Е-001 это 6.89 * 10-1, так что ответ правильный. Просто форма представления вещественных чисел такая.
    Касательно вычисления числа цифр — нести запятую в право, умножая, это правильная мысль. Раз ты знаешь, что такое while, то осталось только придумать условие того, что число сделанных шагов равно количеству знаков в дробной части.

    21 — правильно.

  28. Алексей

    Артур, 23 задачку попробуй как и шестую)

  29. Артур

    Алексей, да у меня еще со школы синусы храмают, я удивляюсь как я шк закончил, справляясь с ними без особых проблем, и 1ый курс универа. Надо взяться и наверстать))))

    А ты есть в ВК?

  30. Taras

    Собственно про синусы ничего знать и не нужно. Требуется преобразовать аргумент с учетом того, что функция 2*pi-периодическая.

  31. Алексей

    program zad23;
    var
    n,y,x: real;
    begin
    write(‘Введите угол n = ‘);
    readln(n);
    y := trunc(n/(2*pi));
    x :=n-2*pi*y;
    writeln(‘ х = ‘, x);
    writeln(‘ sin x = ‘,sin(x));
    writeln(‘ sin n = ‘,sin(n));
    end.
    Только вот не пойму, в задании 23б отрицательный угол нужно преобразовать в диапазон от 0 до 2п или от 0 до -2п?

  32. Алексей

    Артур, да я есть ВК, куда ж без него))) http://vk.com/id12113737

  33. user_q

    Пожалуйстав подскажите по строке 6 — насколько корректно.
    pascalABC.net молчит хотя конструкция неоднозначна, особенно без скобок.
    program Zadanie_18;
    var
    n, m: integer;
    begin
    readln(n, m);
    write(n mod m * 1 div n mod m); {строка 6}
    end.

  34. Taras

    Для Паскаля все однозначно: поскольку деления и умножения имеют равный приоритет, то они выполняются в порядке следования. То есть вычисляется

    (((n mod m) * 1) div n) mod m

    Если хотите другую последовательность операций, нужно расставить скобки.

  35. Аноним

    Да,программирование — это нелегкий труд.Я не одной решить не могу.Понял суть 1,2 и 3 задачи,а написать работающую прогу не могу.К третьей сам написал,но не работает.Почему — не пойму.

  36. Тимофей

    Это я писал ранее.

  37. Тимофей

    Скажите,Тарас Викторович,если на втором листе в среде Паскаля программу запускать,то первая вначале не запускается?

  38. Taras

    >> если на втором листе в среде Паскаля программу запускать,то первая вначале не запускается?

    Да, нет, должна запускаться.

    >> К третьей сам написал,но не работает.Почему — не пойму.

    Если не работает в смысле не запускается, покажи — объясню почему.

  39. Тимофей

    program zadanie chetvertoe;
    var
    n,i,k:integer;
    begin
    write(‘Количество людей в очереди = ‘);
    readln(n);
    write(‘Те, что стоят ближе к началу очереди = ‘);
    readln(i);
    write(‘Те, что стоят ближе к концу очереди = ‘);
    readln(k);
    writeln(‘А это те люди,что стоят между ними = ‘,k-i-1);
    end.

  40. Тимофей

    Что здесь неправильно,Тарас Викторович?

  41. Тимофей

    Вернее третье задание.

  42. Taras

    Название программы не должно содержать пробелов. В остальном все правильно. Разве что по заданию неизвестно, кто ближе к началу i-й или k-й. Чтобы не зависеть от этого, нудно брать модуль разности:

     abs(k-i)-1
  43. Тимофей

    Спасибо,убрал пробел и все путем,не знал про пробел.Буду с другими работать.

  44. Тимофей

    Четвертую решил с тремя программками(там чистая математика,как и везде здесь),а как без if’ов в одну все загнать.Думаю,что это нереально.

  45. Taras

    Вообще-то я так изначально и предполагал, что будет три выражения для трех случаев. Но сделать одно универсальное и без if’ов — тоже не проблема. Там же на 1 разница. Надо всего лишь получить выражение равное нулю или единице, когда числа четные или нечетные.

  46. Тимофей

    На 1,только это уже условие.

  47. Тимофей

    Формула чуть разная для разных случаев.

  48. Taras

    >> Формула чуть разная для разных случаев.

    Не проблема. Ты можешь прибавить или вычесть выражение, которое в одном случае равно 0, а в другом равно 1.

  49. Тимофей

    Не совсем понимаю,как это,немного иначе понимаем мы с вами задачу.Я напишу ее решение, как я его вижу,третьей части,когда а — четное,b — нечетное. И прошу вас свое мне написать — интересно. writeln(‘Нечетных чисел на отрезке = ‘,((b-a+1)/2));можно и по модулю,но это не суть важно.

  50. Taras

    Например, в первой части, когда оба числа четные:

     (b-a) div 2

    В третьей, a — четное, b — нечетное:

     (b-a-1) div 2 

    Оба варианта можно записать одной формулой:

     (b-a-x) div 2 

    где x — равно 0 или 1 в зависимости от четности b. Осталось только придумать выражение для x.

    *Раз мы работаем с целыми, div предпочтительнее, чем «/».

  51. Тимофей

    А как же второй вариант — там х прибавлять надо. Да и еще, не понимаю я не в div, не в mod — их суть, как они работают!?!?!?! Знаю, что write — это аналог print’ в Бейсике, readln — input?, а эти — не понимаю, из-за этого с пятой не справляюсь.

Добавить комментарий