Инструменты пользователя

Инструменты сайта


msx:basic_programming_guide:03

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

msx:basic_programming_guide:03 [2020-03-21 22:52]
msx:basic_programming_guide:03 [2022-09-09 23:26] (текущий)
Строка 1: Строка 1:
-[<>​] +~~HIDEPAGE:​search;​sitemap~~ 
-~~TOC wide~~ +~~REDIRECT>msx:basic_dialogue_programming_language:003~~
- +
-====== Глава III. Программирование разветвляющихся и циклических алгоритмов ====== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-… и если ничто уже не помогает — посмотри инструкцию для пользователя. +
-<WRAP rightalign>​ +
-—//Из завещания неизвестного программиста//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Линейные алгоритмы и соответствующие им программы редко встречаются в практике решения на компьютере реальных задач. Ведь неизменная последовательность действий,​ как правило,​ не может соответствовать изменяющимся обстоятельствам разнообразных жизненных или учебных ситуаций. Чаще всего порядок выполнения действий (ход алгоритмического процесса) зависит от определённых условий,​ поэтому возникает необходимость использовать операторы управления — оператор безусловной передачи управления,​ оператор условной +
-передачи управления,​ оператор цикла. +
- +
-Изучение этих операторов позволит ответить на вопрос:​ может ли //​статический//​ объект текст программы — быть построен таким образом,​ чтобы дать ясное представление о динамической ситуации — её выполнении?​ +
- +
-{{anchor:​goto}} +
-===== III.1. Оператор безусловной передачи управления GOTO ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-…квалификация программистов является убывающей функцией от +
-плотности предложений ''​GOTO''​ в создаваемых ими программах. +
-<WRAP rightalign>​ +
-—//​Э.Дейкстра//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Выполнение операторов в программе осуществляется в порядке их естественного следования. Оператор ''​GOTO''​ ("to go to" — "​перейти"​) позволяет нарушить этот порядок. +
- +
-Оператор безусловной передачи управления имеет следующую структуру:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-GOTO n +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ​  +
-  * ''​GOTO''​ ("to go to" — "​перейти"​) — служебное слово;​ +
-  * n — любой существующий номер строки в программе,​ 0≤n≤65529. +
- +
-Оператор ''​GOTO''​ передаёт управление программной строке с указанным номером n. Если в программе нет строки с этим номером,​ то выдаётся сообщение:​ <WRAP centeralign>"​Undefined line number"​ \\ (//"​Номер строки не определён"//​).</​WRAP>​ +
- +
-Управление передаётся заданной строке,​ даже если в ней нет выполняемого оператора;​ например,​ в строке может находиться оператор ''​REM''​. Поскольку,​ однако,​ оператор ''​REM''​ не исполняется,​ лучше передавать управление следующему за ним исполняемому оператору. В этом случае программа будет выполняться правильно и после удаления программной строки,​ содержащей комментарии. +
- +
-Выполнение оператора ''​GOTO n''​ в режиме прямого выполнения команд аналогично выполнению команды ''​RUN n''​ , но в отличие от этой команды оператор ''​GOTO n''​ начинает выполнение программы с первого оператора указанной строки,​ не присваивая начальных значений переменным и не меняя ранее присвоенных значений. С этой точки зрения оператор ''​GOTO n''​ в режиме прямого выполнения команд полезен при //​отладке и тестировании//​. В остальных случаях использовать его в этом режиме не рекомендуется,​ поскольку существует большая вероятность задать неправильный номер строки или непреднамеренно изменить значение переменной так, что фактически изменится порядок работы программы,​ что приведёт к появлению многочисленных ошибок! +
- +
-Оператор ''​GOTO''​ — одна из наиболее интуитивно ясных и в то же время одна из наиболее опасных конструкций языков программирования. Оператором ''​GOTO''​ следует пользоваться как можно //​реже//,​ так как он делает программу трудно читаемой для программиста — приходится особо следить за тем, в каком порядке выполняются строки программы. Отметим,​ что в школьный алгоритмический язык эта конструкция не включена вообще! +
- +
-__//​Примеры//​__:​ +
-  * 1)<​code>​ +
-20 GOTO 20 '​Зацикливание обеспечено! Стандартный приём при работе с графикой. +
-</​code>​ +
-  * 2)<​WRAP><​code>​ +
-NEW +
-Ok +
-5'​Пример плохой,​трудно читаемой программы! +
-10 INPUT X +
-20 GOTO 40 +
-30 PRINT X+Y:GOTO 60 +
-40 INPUT Y +
-50 GOTO 30 +
-60 END +
-</​code>​ +
-Нетрудно видеть,​ что приведённая программа эквивалентна программе,​ состоящей из единственной программной строки:​ +
-<​code>​ +
-10 INPUT X,Y:PRINT X+Y:END +
-</​code>​ +
-</​WRAP>​ +
-  * 3)<​WRAP><​code>​ +
-  NEW +
-  Ok +
-  10 PRINT "​2*2=4":​GOTO 10 +
-</​code>​ +
-Эта программа никогда не закончит свою работу,​ т.к.после вывода текста "​2*2=4"​ на экран оператор ''​GOTO 10''​ возвращает к строке 10, которая опять выводит "​2*2=4"​ и т.д. Пользователь,​ разумеется,​ может вмешаться и остановить такую "​вечно"​ работающую программу(её называют //​зациклившейся//​) — для этого одновременно нажимают клавиши <​key>​CTRL</​key>​ и <​key>​STOP</​key>​ (напомним,​ что такое нажатие обозначается <​key>​CTRL+STOP</​key>​). +
-</​WRAP>​ +
- +
-В случае,​ если оператор записывается двумя служебными словами ''​GO TO n'',​ то он выполняется аналогично — этот формат сохранен для совместимости с другими языками программирования. +
- +
-Однако,​ использовать "​двухсловную"​ форму ''​GOTO''​ не рекомендуется,​ так как она требует большого объёма памяти для хранения. Достигаемая экономия на первый взгляд несущественна,​ однако рано или поздно многие программисты попадают в ситуацию,​ когда "​нескольких бит не хватает!"​ +
- +
-В статье Бема и Якопини [[bibliography#​b40|[40]]] было показано,​ что любой алгоритм может быть описан на языке программирования,​ использующем //​только три// управляющие структуры:​ следование,​ цикл и ветвление. Возможность представления любых алгоритмов с помощью вложенных друг в друга структур следования,​ цикла и ветвления составляют основу метода структурного программирования. +
- +
-В последующих разделах мы расскажем об операторах ''​IF…THEN…ELSE''​ и ''​FOR…NEXT'',​ которые являются простейшими эквивалентами управляющих конструкций Бема и Якопини. +
- +
-{{anchor:​ifthenelse}} +
-===== III.2. Оператор условной передачи управления IF ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-ЕСЛИ нельзя,​ но очень хочется,​ ТО можно! +
-<WRAP rightalign>​ +
-—//​Евг.Сазонов,​ программовед и языколюб//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Сказочные герои, как известно,​ по дороге за тридевять земель в тридесятое царство встречали на перекрёстке камень с надписью — альтернативой. У программиста при написании программы возникает потребность запрограммировать альтернативу,​ т.е. предусмотреть возможность выбора одного,​ либо другого действия в зависимости от некоторого условия. Для программирования +
-таких разветвляющихся участков алгоритма используется оператор условной передачи управления ''​IF''​. +
- +
-Структура оператора:​ +
-<​code>​ +
-IF условие THEN список операторов [ELSE список операторов] +
-</​code>​ +
-Здесь:​ +
-  * ''​IF''​("​если"​),​ ''​THEN''​("​то"​),​ ''​ELSE''​("​иначе"​) — служебные слова;​ +
-  * //​условие//​ — арифметическое или логическое выражение;​ +
-  * //​список операторов//​ — несколько (или ни одного) операторов [[msx:basic:]], разделённых двоеточиями,​ или номер существующей программной строки. +
- +
-Напомним,​ что квадратные скобки — обозначение,​ указывающее,​ что синтаксическая конструкция внутри них не является обязательной! +
- +
-{{anchor:​ifgotoelse}} +
- +
-Кроме того, вместо служебного слова ''​THEN''​ может быть использовано служебное слово ''​GOTO'',​ при этом за ''​GOTO''​ должен следовать номер существующей программной строки. Более того, в случае,​ когда //​список операторов//​ состоит лишь из оператора ''​GOTO n'',​ служебное слово ''​GOTO''​ может опускаться. +
- +
-Таким образом,​ если мы обозначим:​ +
-  * n1  и  n2 — номера программных строк,​ +
-  * О1  и  О2 — последовательности операторов [[msx:​basic:​]] (операторы внутри каждой последовательности разделяются символом ":"​),​ то можно записать следующие формы оператора ''​IF'':​ +
-<​code>​ +
-IF  условие ​ THEN  О1 +
-IF  условие ​ ТHEN  n1 +
-IF  условие ​ GOTO  n1 +
-IF  условие ​ THEN  O1  ELSE  O2 +
-IF  условие ​ THEN  O1  ELSE  n2 +
-IF  условие ​ ТHEN  n1  ELSE  O2 +
-IF  условие ​ ТHEN  n1  ELSE  n2 +
-IF  условие ​ GOTO  n1  ELSE  O2 +
-IF  условие ​ GOTO  n1  ELSE  n2 +
-IF  условие ​ GOTO  O1  ELSE  O2  (обратите внимание!) +
-</​code>​ +
-Отметим,​что в некоторых версиях BASIC (например,​ для ПЭВМ"​ДВК–2М"​) реализованы только "​усечённые"​ конструкции оператора ''​IF''​ — без ветви "​иначе"​ (т.е. без служебного слова ''​ELSE''​):​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-IF условие THEN n1  +
- +
-IF условие THEN O1 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Теперь рассмотрим несколько примеров:​ +
-  * 1) <​WRAP>​ <​code>​ +
-300 DEFDBL A,B:IF A=B GOTO 700 +
-</​code>​ +
-Внимание! Может оказаться,​ что два числа, которые должны быть //​равными//,​ всё–таки //​немного//​ отличаются из–за ошибок округления! Переход на строку с номером 700 может не осуществиться! +
- +
-Правильной будет следующая запись строки 300: +
-<​code>​ +
-300 DEFDBL A,B:IF ABS(A-B)<​=EPS GOTO 700 +
-</​code>​ +
-где EPS — допустимая "​точность несовпадения"​ чисел A и B. +
- +
-Напомним,​ что основное различие между целыми и действительными (с фиксированной или плавающей точкой) константами в том, что целые константы представлены в компьютере //​точно//,​ а действительные — лишь //​приближённо//​. Выполняя операции с действительными числами,​ мы //​обязательно//​ должны считаться с погрешностью округления,​ которая может очень сильно исказить результат! +
-Взгляните:​ +
-<​code>​ +
-10 INPUT А +
-20 ? (A/3)^2*9 +
-run +
-? 4 +
- ​15.999999999999 +
-Ok +
- +
-10 INPUT A! +
-20 PRINT A!/3*3 +
-run +
-? 1 +
- ​.99999999999999 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * 2) <​WRAP>​ <​code>​ +
-10 INPUT A,A! +
-20 IF A!=A THEN PRINT "​Верно!":​END ELSE PRINT "​Посмотрите комментарий к предыдущему примеру!":​END +
-run +
-? 0.000001000002,​0.000001000002 +
-Посмотрите комментарий к предыдущему примеру! +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * 3) <​WRAP>​ <​code>​ +
-10 IF A<B THEN Y=X^2:END ELSE Y=X^3:END +
-20 '​Использование оператора END в операторе IF +
-</​code>​ +
-</​WRAP>​ +
-  * 4) <​WRAP><​code>​ +
-100 IF X/​N=FIX(X/​N) THEN PRINT"​X делится на N!" +
-</​code> ​  +
-или +
-<​code>​ +
-100 IF X MOD N=0 THEN PRINT"​X делится на N!" +
-</​code>​ +
-или +
-<​code>​ +
-100 IF X/​N=INT(X/​N) THEN PRINT"​X делится на N!" +
-</​code>​ +
-Однако обратите внимание на следующий фрагмент:​ +
-<​code>​ +
-10 X=LOG(EXP(1)):​N=1 +
-20 IF X/​N=INT(X/​N) THEN ?"​Ура!":​END ELSE ?"​О,​ужас!":​ +
-END +
-run +
-О,​ужас! +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * 5) <​WRAP><​code>​ +
-NEW +
-Ok +
-10 INPUT A,B +
-20 IF A>B THEN DIM C(4) ELSE DIM C(7) +
-30 C(6)=1:​PRINT C(6) +
-run +
-? 1,3 +
- 1 +
-Ok +
- +
-run +
-? 3,1 +
-Subscript out of range in 30 +
-Ok +
-</​code>​ +
-Сообщение об ошибке "​Subscript out of range" переводится как //"​Выход за границы массива"//,​ то есть обращение к элементу массива со значением индекса,​ выходящим за пределы границ измерения массива. +
- +
-Таким образом,​ в некоторых случаях вместо использования "​стирающего"​ оператора ''​ERASE''​ (см. [[01#I.5. Массивы переменных. Оператор ERASE|раздел I.5.]]) для переопределения размерности массива в программе можно применять указанный приём. +
-</​WRAP>​ +
-  * 6) <​WRAP><​code>​ +
-Ok +
-?​11*(1/​11) +
- 1 +
-Ok +
-</​code>​ +
- +
-Однако естественно возникновение вопроса:​ почему компьютер выводит число 1 в качестве результата вычисления выражения 11*(1/​11)?​ +
- +
-Объяснение этого факта следует искать в особенностях работы процедуры вывода,​ инициализируемой оператором ''​PRINT'',​ а именно:​ эта процедура самостоятельно выполняет определённые операции округления выводимых числовых данных. Однако результаты подобных округлений,​ как видно из приведённых примеров,​ труднопредсказуемы,​ что в свою очередь может приводить к непредвиденным последствиям. +
- +
-__Замечание__. \\ +
-Будьте осторожны при записи условий,​ ибо посмотрите:​ +
-<​code>​ +
-10 IF Z%=&B11 THEN PRINT "​1"​ ELSE PRINT "​0"​ +
-run +
-Sintax error in 10 +
-</​code>​ +
-Исправить ошибку можно, заключив &''​В11''​ в круглые скобки! +
-</​WRAP>​ +
- +
-Напомним,​ что //​семантика//​ (от греч."​semantikos"​ — "​обозначающий"​) — значения единиц языка, а //​синтаксис//​ (от греч."​syntaxis"​ — "​построение,​порядок"​) — способы соединения слов (и их форм) в словосочетания,​ предложения и текст. +
- +
-Опишем семантику конструкции ''​IF…THEN…ELSE… ''​. Вначале вычисляется значение условия. Если в качестве условия записано строковое выражение,​ то выдаётся сообщение об ошибке:​ <WRAP centeralign>"​Type mismatch"​ \\ (//"​Несоответствие типов"//​).</​WRAP>​ +
- +
-Если условие истинно (TRUE), то управление передаётся фразе ''​THEN'';​ если условие ложно (''​FALSE''​) и есть фраза ''​ELSE'',​ то управление передаётся фразе ''​ELSE'';​ если условие ложно (''​FALSE''​) и нет фразы ''​ELSE'',​ то управление передаётся первому оператору //​следующей//​ программной строки (то есть условно можно считать,​ что фраза ''​ELSE''​ есть, но за ней стоит "​пустой"​ оператор,​ не производящий никаких действий). +
- +
-Если непосредственно за ''​THEN''​ или ''​ELSE''​ указан номер программной строки и управление передаётся этой фразе, то фактически выполняется оператор +
-<​code>​ +
-GOTO Номер строки +
-</​code>​ +
-В качестве примера рассмотрим программу,​ вычисляющую и показывающую на экране наибольший общий делитель (НОД) двух натуральных чисел M и N, введённых пользователем. Программа использует //​алгоритм Евклида//,​ который основывается на том, что НОД пары различных натуральных чисел совпадает с НОД пары, полученной из предыдущей заменой большего числа разностью большего и меньшего чисел. +
-<​code>​ +
-NEW +
-Ok +
-20 DEFINT M,​N:​INPUT"​Введите M,​N";​M,​N +
-50 IF M>N THEN M=M-N +
-60 IF M<N THEN N=N-M +
-70 IF M<>N THEN GOTO 50 +
-80 PRINT "​НОД...";​M:​END +
- +
-run +
-Введите M,N? 34,51 +
-НОД... 17 +
-Ok +
- +
-run +
-Введите M,N? 15,625 +
-НОД... 5 +
-Оk +
-                        +
-run +
-Введите M,N? 11,121 +
-НОД... 11 +
-Ok +
-</​code>​ +
- +
-Проследим теперь за работой компьютера. При первом обращении к строке 50 переменная М имеет значение 34, а переменная N — значение 51. Условие M>N не соблюдено,​ поэтому следует переход к строке 60. Условие M<N соблюдено,​ N получает новое значение 51-34=17. Условие M<>N (M не равно N) тоже соблюдено и поэтому строка 70 передаёт управление назад, строке 50. +
- +
-Теперь M имеет значение 34, а N — значение 17, и условие M>N соблюдено;​ поэтому переменной M присваивается значение 34-17=17. M=N=17. Условие строки 60 не соблюдено,​ условие M<>N строки 70 тоже не соблюдено,​ и компьютер,​ наконец,​ выполняет строку 80,​выводящую на экран дисплея текст "​НОД… 17". В строке 80 работа программы заканчивается. Эта короткая программа позволяет найти НОД для любой пары натуральных чисел — выполнение серии строк 50, 60, 70 всегда будет повторено необходимое число раз. Об этом "​заботятся"​ операторы ''​IF…THEN''​ ! +
- +
-В качестве ещё одного примера приведём программу вычисления наименьшего общего кратного (НОК) двух натуральных чисел. В алгоритме используем тот факт, что произведение НОК и НОД двух чисел равно произведению самих чисел (в программе — переменная К). +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT M,​N,​K:​INPUT"​Введите M,​N";​M,​N:​K=M*N +
-20 IF M>N THEN M=M-N +
-30 IF N>M THEN N=N-M +
-40 IF M<>N THEN 20 +
-50 PRINT "​НОК...";​K/​M:​END +
-run +
-Введите M,N? 4,6 +
-НОК... 12 +
-Оk +
- +
-run +
-Введите M,N? 12,45 +
-НОК... 180 +
-Ok +
- +
-run +
-Введите M,N? 888,117 +
-НОК... 103896 +
-Ok +
-</​code>​ +
-//​Важное замечание//:​ оператор ''​IF''​ должен полностью размещаться в одной программной строке (программная строка,​ вообще говоря,​ отлична от дисплейной строки!) и быть последним в ней. В этом случае будьте внимательны:​ программная строка должна включать не более 255 символов (вместе с номером)! +
- +
-Однако не всегда удаётся "​втиснуть"​ в одну программную строку последовательности операторов O1 и O2. В таких случаях помогает оператор ''​GOTO'',​ который передаёт управление на строку,​ с которой начинается нужный фрагмент программы (если необходимо вернуться к строке программы,​ следующей за условным оператором,​ то в конце фрагмента опять приходится ставить оператор ''​GOTO''​). Такая конструкция весьма громоздка,​ поэтому предпочтительнее использовать подпрограммы (см. [[04#IV.4. Подпрограммы|раздел IV.4.]]). +
- +
-Любое арифметическое выражение может быть использовано в качестве //​условия//;​ при этом следует помнить,​ что если результат его вычисления отличен от нуля, то значением условия является TRUE, во всех остальных случаях — ''​FALSE''​. +
- +
-__//​Пример//​__. +
-<​code>​ +
-IF X <> 0 THEN …''​ идентично записи ''​IF X THEN … +
-</​code>​ +
- +
-Отметим,​ что //​список операторов//​ может содержать оператор ''​IF…THEN…ELSE…''​ (в этом случае говорят о //​вложении//​ операторов ''​IF''​ друг в друга). +
- +
-Например,​ алгоритм нахождения большего из трёх чисел A, B и C можно записать при помощи оператора:​ +
-<​code>​ +
-10 IF A>B THEN IF A>C THEN Z=A ELSE Z=C ELSE IF B>C THEN Z=B ELSE Z=C +
-11 ' Не правда-ли,​ элегантно (!) и непонятно?​ +
-</​code>​ +
-Сравните:​ +
-<​code>​ +
-10 BIG=X +
-20 IF Y>BIG THEN BIG=Y +
-30 IF Z>BIG THEN BIG=Z +
-</​code>​ +
- +
-При вложении операторов IF возникают определённые логические трудности,​ связанные с проблемой "​болтающегося ELSE". В самом деле, если написать оператор вида: +
-<​code>​ +
-IF условие1 THEN IF условие2 THEN O1 ELSE O2 +
-</​code>​ +
-то сразу же возникает вопрос:​ к какому ''​IF''​ (первому или второму) принадлежит фраза ''​ELSE O2''​ (как говорят,​ ''​ELSE''​ "​болтается"​!)?​ +
- +
-Для устранения возможной двусмысленности учтите,​ что любой ''​ELSE''​ "​связывается"​ с ближайшей //​предшествующей//​ ему в программной строке конструкцией ''​IF…THEN'',​ которой ещё не поставлен в соответствие ''​ELSE''​ (сравните с расстановкой скобок в алгебраическом выражении!). +
- +
-Поэтому можно сформулировать простое //​правило//:​ добавляйте нужное количество "​пустых"​ ''​ELSE'',​ начиная с конца программной строки,​ для удовлетворения всех вхождений ''​IF…THEN''​ (сравните с правилом "​вложенного IF"​на языке программирования PL/1: каждая из вложенных конструкций ''​IF…THEN''​ должна иметь соответствующий ''​ELSE'',​ возможно "​пустой"​). +
- +
-Таким образом,​ конструкция +
-<​code>​ +
-IF условие1 THEN IF условие2 THEN O1 ELSE O2 +
-</​code>​ +
-понимается как +
-<​code>​ +
-IF условие1 THEN ( IF условие2 THEN O1 ELSE O2 ) +
-</​code>​ +
- +
-Скобки поставлены //​только//​ для наглядности. Упаси Вас бог употребить их в программе! Но если Вам всё–таки хочется выделить в программе группу операторов,​ то можете применить для этой цели последовательность двоеточий :: … :. +
- +
-Например:​ +
-<​code>​ +
-IF условие1 THEN:::IF условие2 THEN O1 ELSE O2::: +
-</​code>​ +
- +
-Смысл конструкции можно изменить,​ добавив "​пустой"​ ''​ELSE'':​ +
-<​code>​ +
-IF условие1 THEN:::IF условие2 THEN O1 ELSE:::ELSE O2 +
-</​code>​ +
- +
-В какой–то мере последовательность двоеточий играет роль операторных скобок,​ присущих,​ например,​ языкам ALGOL, PL/1, Pascal, C ! +
- +
-__//​Примеры//​__:​ +
-  * 1) {{anchor:​e032-01}} {{.examples:​032-01.bas|}} \\ [[+tab|wmsxbpge>​032-01.bas]]<​code>​ +
-NEW +
-Ok +
-10 INPUT X +
-20 IF X>1 THEN IF X<3 THEN PRINT "​1≤X<​3":​END ELSE PRINT "​X>​3":​END +
-30 PRINT "​X≤1"​ +
-run +
-? 0 +
-X≤1 +
-Ok +
- +
-run +
-? 1 +
-X≤1 +
-Ok +
- +
-run +
-? 2.5 +
-1≤X<​3 +
-Ok +
- +
-run +
-? 4 +
-X>3 +
-Ok +
-</​code>​ +
-  * 2) {{anchor:​e032-02}} {{.examples:​032-02.bas|}} \\ [[+tab|wmsxbpge>​032-02.bas]]<​code>​ +
-NEW +
-Ok +
-10 INPUT X +
-20 IF X>1 THEN IF X<3 THEN PRINT "​1≤X<​3":​END ELSE ELSE PRINT "​X≤1":​END +
-30 PRINT "​X≥3"​ +
-run +
-? 0 +
-X≤1 +
-Ok +
- +
-run +
-? 1 +
-X≤1 +
-Ok +
- +
-run +
-? 2.5 +
-1≤X<​3 +
-Ok +
- +
-run +
-? 4 +
-X≥3 +
-Ok +
-</​code>​ +
-  * <​WRAP>​ 3) составить программу,​ определяющую,​ каким должен быть Ваш идеальный вес, по следующему алгоритму (формула Мэгони,​ уточнённая К. Купером). Мужчина берет свой рост в дюймах,​ умножает это число на 4 и вычитает 128. Женщине надо умножить свой рост в дюймах на 3.5 и затем вычесть 108. Эта формула рассчитана на мужчину со средней шириной кости и женщину среднего телосложения. Но Вы можете заметить:​ "У меня широкая кость. Годится ли мне эта формула?"​ Да, но тогда прибавьте 10% к окончательному результату. Что бы определить,​ насколько широка у Вас кость, используйте следующее правило. Измерьте окружность запястья доминирующей руки, т.е. руки, которой Вы пишите. Мужчина имеет широкую кость, если окружность его запястья больше 18 см, женщина — больше 16.5 см. Если размер окружности запястья меньше,​ то говорят о среднекостном или о тонкокостном типе сложения. +
- +
-Описанная выше формула предполагает измерение роста в футах и дюймах,​ а веса — в фунтах. Напомним,​ что +
-  * 1 фут = 0.3048 м, +
-  * 1 дюйм = 0.0254 м, +
-  * 1 фунт = 0.4536 кг. +
-\\ {{anchor:​e032-03}} {{.examples:​032-03.bas|}} \\ [[+tab|wmsxbpge>​032-03.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT"​Если Вы мужчина,​ то нажмите клавишу '​SHIFT'​+'​1',​а если Вы женщина,​ то нажмите клавишу '​клюшка'";​X% +
-20 INPUT "​Укажите Ваш рост в метрах";​L +
-30 INPUT"​Укажите обхват запястья сильнейшей руки в см";​Y +
-35 PRINT"​Ваш идеальный вес :" +
-40 IF X%=1 THEN IF Y>18 THEN PRINTUSING"###​.###";​(L/​.0254*4-128)*.4536*1.1;​ELSE PRINTUSING "###​.###";​ (L/​.0254*4-128)*.4536;​ELSE IF Y>16.5 THEN PRINTUSING "###​.###";​L/​.0254*3.5-108)*.4536*1.1;​ELSE PRINTUSING "###​.###";​(L/​.0254*3.5-108)*.4536;​ +
-50 PRINT " кг":​END +
-run +
- +
-Если Вы мужчина,​ то нажмите клавишу '​SHIFT'​+'​1',​ а если Вы женщина,​ то нажмите клавишу '​клюшка'?​ 1 +
-Укажите Ваш рост в метрах?​ 1.745 +
-Укажите обхват запястья сильнейшей руки в см? 18.5 +
-Ваш идеальный вес: +
- ​73.249 кг +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * <​WRAP>​ 4) составить программу решения квадратного уравнения  +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-a·x² + b·x + c = 0 +
-</​code>​ +
-</​WRAP>​ +
- +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-{{anchor:​e032-04}} {{.examples:​032-04.bas|}} \\ [[+tab|wmsxbpge>​032-04.bas]] +
-<​code>​ +
-NEW +
-Ok +
-100 INPUT"​Задайте a,​b,​c";​A,​B,​C +
-110 DISC=B*B-4*A*C:​W=1/​2/​A:​Z=-B/​2/​A +
-120 IF ABS(DISC)<​1.E-14 THEN PRINT"​Двойной корень,​x=";​Z:​GOTO 100'​Условие ABS(DISC)<​1.E-14 взято вместо условия DISC=0 с целью компенсации ошибок округления. +
-130 IF DISC<0 THEN 160 +
-140 PRINT "​Корни";​Z+SQR(DISC)*W;​ +
-150 PRINT "​и";​Z-SQR(DISC)*W:​GOTO 100 +
-160 PRINT "​Мнимые корни:";​Z;"​+/​-";​SQR(-DISC)*W;"​i":​GOTO100 +
-run +
- +
-Задайте a,b,c? 1,2,1 +
-Двойной корень,​x=-1 +
-Задайте a,b,c? 1,1,1 +
-Мнимые корни:​-.5 +/- .8660254037844 i +
-Задайте a,b,c? 1,-5,6 +
-Корни 3 и 2 +
-Задайте a,b,c? 0,1,1 +
-Division by zero in 110 +
-Ok +
-</​code>​ +
- +
-Заметим,​ что указанная программа "не работает"​ в том случае,​ когда а=0. Поэтому добавим к программе строку:​ +
-<​code>​ +
-105 IF A=0 THEN IF B=0 THEN IF C=0 THEN PRINT"​x-любое":​GOTO 100 ELSE PRINT"​решений нет":​GOTO 100 ELSE PRINT"​корень равен";​-C/​B:​GOTO 100 +
-</​code>​ +
-Это приведёт к следующему результату:​ +
-<​code>​ +
-run +
-Задайте a,b,c? 0,0,0 +
-x-любое +
-Задайте а,b,c? 0,1,1 +
-корень равен-1 +
-Задайте a,b,c? 0,0,1 +
-решений нет ​              и так далее… +
-</​code>​  +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Целые числа сотворил господь бог, всё остальное — дело рук человеческих. +
-<WRAP rightalign>​ +
-—//​Л.Кронекер//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-</​WRAP>​ +
-  * <​WRAP>​ 5) написать программу,​ которая выводит на экран разложение введённого в компьютер натурального числа на простые сомножители,​ например,​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-24=2*2*2*3, ​ 17=17 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-Напомним //​основную теорему арифметики//​. +
- +
-Любое натуральное число n>2 может быть представлено в виде произведения простых множителей;​ с точностью до порядка множителей такое представление единственно. +
- +
-{{anchor:​e032-05}} {{.examples:​032-05.bas|}} \\ [[+tab|wmsxbpge>​032-05.bas]] +
-<​code>​ +
-10 PRINT "​Введите натуральное N,​N>​1"​ +
-20 INPUT N:PRINT N;"​=";:​P=2 +
-30 D=N/P +
-40 IF D=INT(D) THEN ?​S$;​P;:​S$="​*":​N=D:​GOTO 30 ELSE P=P+1 +
-50 IF N>=P THEN 30 +
-60 PRINT:END +
- +
-run +
-Введите натуральное N,N>1 +
-? 111 +
- 111 = 3 * 37 +
-Ok +
- +
-run +
-Введите натуральное N,N>1 +
-? 1111 +
- 1111 = 11 * 101 +
-Ok +
-</​code>​ +
-Далее, легко получаются следующие результаты:​ +
-<​code>​ +
-          11111 = 41 * 271 +
-         ​111111 = 3 * 7 * 11 * 13 * 37 +
-        1111111 = 239 * 4649 +
-       ​11111111 = 11 * 73 * 101 * 137 +
-              …          … +
- ​11111111111111 = 11 * 239 * 4649 * 909091 +
-</​code>​ +
- +
-Объектом исследования в данной программе являются числа, записанные цепочкой единиц,​ //​репьюниты//​ (от английского "​repeated unit" — "​повторенная единица"​):​ 1,11,111, и т.д. Этот термин придумал в 1964 году американец А. Бейлер. Первую же работу об этих удивительных числах написал двумя столетиями раньше Иоганн–III Бернулли в связи с исследованиями периодических десятичных дробей. В 1895 году француз Э.Люка в книге "​Занимательная математика"​ публикует проверенную им таблицу всех простых делителей репьюнитов до 18–го репьюнита включительно. +
- +
-В частности,​ +
-<​code>​ +
-   ​111111111111111 = 3*37*31*41*271*290*6161 +
-  1111111111111111 = 11*17*73*101*137*5882353 +
- ​11111111111111111 = 2071723*5363222357 +
-111111111111111111 = 3*7*11*13*19*37*52579*333667 . +
-</​code>​ +
- +
-Сегодня таблица делителей репьюнитов достигла n=3000 (С. Ейтс, 1975), однако в ней ещё достаточно много пробелов,​ и даже не всё ясно в первой сотне репьюнитов. Практический интерес к репьюнитам существует в теории арифметических кодов, служащей основой помехоустойчивого кодирования в компьютерной технике,​ и в проблеме простых чисел: их ищут сейчас в основном среди так называемых //​чисел Мерсенна//,​ имеющих вид +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-2ⁿ-1 ,  n=1,​2,​3,​… +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-и последним достижением на этом пути стало число +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
- ​132049 +
-2      - 1    (1984 год) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-А ведь числа Мерсенна — это репьюниты в двоичной системе счисления! Проверьте этот факт! +
-</​WRAP>​ +
- +
-Обязательно проведите аналогию между оператором условной передачи управления ''​IF''​ в языке программирования [[msx:​basic:​]] и командой ветвления \\ +
-__если__ ​ условие \\ +
-│    __то__ серия 1 \\ +
-│    __иначе__ серия 2 \\ +
-__всё__ +
-\\  +
-в школьном алгоритмическом языке! +
-Кстати отметим,​ что аналог служебного слова __всё__ в [[msx:​basic:​]] не нужен — признаком конца оператора ''​IF''​ является конец программной строки,​ в которой он находится. +
- +
-В школьном алгоритмическом языке введена ещё одна команда — команда //​проверки контрольного условия//​ +
- +
-''​__утв__ //​условие//''​ +
- +
-Если в процессе исполнения алгоритма условие нарушается,​ то компьютер прекращает исполнение алгоритма и сообщает,​ что возник отказ.  +
- +
-Аналогом данной команды в [[msx:​basic:​]] может служить,​ например,​ конструкция ''​IF…THEN…ELSE''​ в следующем примере:​ +
-{{anchor:​e032-06}} {{.examples:​032-06.bas|}} \\ [[+tab|wmsxbpge>​032-06.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 '​Вычисление значения функции y=√(x-2) +
-20 INPUT"​Введите X";X  +
-30 IF X>=2 THEN PRINT SQR(X-2) ELSE PRINT 1/0 +
-run +
-Введите X? 4 +
- ​1.414213562373 +
-Ok +
- +
-run +
-Введите X? +
-Division by zero in 30 +
-Ok +
-</​code>​ +
- +
-{{anchor:​ongoto}} +
-===== III.3. Оператор ON GOTO ===== +
- +
-Общая форма записи оператора–переключателя (оператора выбора по целому значению) следующая:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-ON β GOTO N1, N2, …, Nk +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​ON''​ ("​на"​),​ ''​GOTO''​ ("​идти к") — служебные слова;​ +
-  * β — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,255]; +
-  * N1, N2, …, Nk — номера программных строк; оператор ''​ON GOTO''​ воспринимает столько номеров строк в списке,​ сколько Вы сможете записать в одной логической строке (помните,​ что она ограничена 255 символами!). +
- +
-Выполнение оператора ''​ON''​ начинается с вычисления целой части значения арифметического выражения β, которое мы обозначим p. +
- +
-Далее, если p∈{1, 2,… , k}, k — натуральное число, то управление переходит к строке Np. +
- +
-Если p=0 или p>k, то выполняется оператор,​ следующий за ''​ON''​. +
- +
-Если же p<0, то последует сообщение об ошибке:​ <WRAP centeralign>"​Illegal function call" \\ (//"​Неправильный вызов функции"//​).</​WRAP>​ +
- +
-__//​Примеры//​__:​ +
-  * <​WRAP>​ 1) {{anchor:​e033-01}} {{.examples:​033-01.bas|}} \\ [[+tab|wmsxbpge>​033-01.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT X +
-20 ON X GOTO 200,​300,​400:?​ X:GOTO 10 +
-200 PRINT X+200:END +
-300 PRINT X+300:END +
-400 PRINT X+400:END +
- +
-run +
-? 0 +
- 0 +
-? 3 +
- ​403 ​                          +
-Ok +
- +
-run +
-? -1 +
-Illegal function call in 20 +
-Ok +
- +
-run +
-? 2 +
- 302 +
-Ok +
- +
-run +
-? 1 +
-201 +
-Ok +
-</​code>​ +
- +
-Оператор ''​ON GOTO''​ удобен,​ когда выполнение одной или нескольких различных ветвей алгоритма определяется значением переменной или выражения (так называемый выбор //по значению//​). Если эти ветви //​короткие//,​ то смело используйте оператор ''​ON GOTO''​. Если же ветви имеют достаточно сложную логику и могут быть оформлены как //​подпрограммы//,​ то для реализации выбора по значению используйте оператор ''​ON GOSUB''​ (см. [[04#IV.5. Оператор ON GOSUB|раздел IV.5.]]). +
-</​WRAP>​ +
-  * <​WRAP>​ 2) {{anchor:​e033-02}} {{.examples:​033-02.bas|}} \\ [[+tab|wmsxbpge>​033-02.bas]] <​code>​ +
-NEW +
-Ok +
-5 '​Анализ символов,​ вводимых с клавиатуры +
-10 ON ASC(INPUT$(1))-26 GOTO 101,​102,​103 +
-101 GOTO 10 +
-102 PRINT "​Нажата клавиша ──▶":​END +
-103 PRINT "​Нажата клавиша ◀──":​END +
-run                                          ┌─────┐ +
-Нажата клавиша ──▶ ​          ​Нажмите клавишу │ ──▶ │  ! +
-Ok                                           ​└─────┘ +
-run                                          ┌─────┐ +
-Нажата клавиша ◀── ​          ​Нажмите клавишу │ ◀── │  ! +
-Ok                                           ​└─────┘ +
-run                                          ┌─────┐ +
-Illegal function call in 10  Нажмите клавишу │ TAB │ ! +
-Ok                                           ​└─────┘ +
-</​code>​ +
- +
-О строковой функции ''​INPUT$()''​ см. в [[07#​VII.1.1. Нестандартный ввод с клавиатуры|разделе VII.1.1]]. +
-</​WRAP>​ +
-  * <​WRAP>​ 3) Оператор +
-<​code>​ +
-ON A GOTO 110,​110,​110 +
-</​code>​ +
-позволяет совершить переход к программной строке 110, если значение переменной А находится в полуинтервале [1,4). +
-</​WRAP>​ +
-  * <​WRAP>​ 4) Пусть в программе требуется выполнить три различные операции в зависимости от значения переменной K, которое может быть меньше,​ больше или равно нулю. +
- +
-Приведём фрагмент программы:​ +
-<​code>​ +
-110 ON SGN(K)+1 GOTO 170,210 +
-120 '​Выполнение операции при K<0 +
-             … +
-170 '​Выполнение операции при K=0 +
-             … +
-210 '​Выполнение операции при K>0 +
-             … +
-</​code>​ +
-</​WRAP>​ +
-  * <​WRAP>​ 5) Пусть в программе требуется совершить переход к различным строкам,​ если значение переменной A находится в следующих диапазонах:​ +
-     ​0≤A<​ 800 — переход к строке 900; +
-   ​800≤A<​1600 — переход к строке 800; +
-  1600≤A<​2400 — переход к строке 700. +
-Если же A≥2400, то должен выполняться следующий оператор. В этом случае программная строка с оператором ''​ON''​ будет иметь вид: +
-<​code>​ +
-50 ON A/800+1 GOTO 900,​800,​700 +
-</​code>​ +
-</​WRAP>​ +
- +
-Заметим,​ что оператор ''​ON GOTO''​ потенциально опасен,​ особенно для начинающих,​ так как его неаккуратное использование может привести к запутанной,​ трудной для понимания программе. +
- +
-В заключение проведём аналогию между оператором ON GOTO и командой //​выбор//​ в сокращённом варианте \\ +
-__выбор__ \\ +
-│     ​__при__ ​ условие 1: серия 1 \\ +
-│     ​__при__ ​ условие 2: серия 2 \\ +
-│     … \\ +
-│     ​__при__ ​ условие N: серия N \\ +
-__всё__\\ +
-в школьном алгоритмическом языке. Говорят,​ что команда выбора реализует "​выбор //по условию//"​. Выбор по условию введён в школьный алгоритмический язык из языка программирования Рапира. В большинстве языков высокого уровня (в том числе и в [[msx:​basic:​]]!) этой конструкции в чистом виде нет, но её можно моделировать следующей последовательностью вложенных команд ветвления:​ \\ +
-__если__ условие 1 \\ +
-│     ​__то__ серия 1 \\ +
-│     ​__иначе__ ​ если условие 2 \\ +
-│          │     ​__то__ серия 2 \\ +
-│          │     ​__иначе__ … \\ +
-│          │            __если__ условие N \\  +
-│          │          │     ​__то__ серия N \\ +
-│          │            __всё__ \\ +
-│          │          … \\ +
-│            __всё__ \\ +
-__всё__ \\ +
- +
- +
-Зато в версии [[msx:​basic:​]] есть оператор ''​ON GOTO''​ — другая форма выбора (по //​значению//​ выражения). +
- +
-Ясно, что, вообще говоря,​ механизмы работы выбора по условию и по значению совпадают. Отличие лишь в форме условия:​ в выборе по условию оно может быть любым, а в выборе по значению условие определяется значением арифметического выражения. +
- +
-{{anchor:​fornext}} +
-===== III.4. Программирование циклов ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Три месяца каждую вторую среду он ходил смотреть фильм +
-"​Девушка моей мечты",​ но на связь с ним никто не вышел. +
-<WRAP rightalign>​ +
-—//​В.Кожевников//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Понятие цикла является одним из основополагающих понятий информатики. Считается,​ что если бы в программах не было возможности организовывать циклы, то применять ЭВМ для решения многих задач не имело бы никакого смысла. +
- +
-//​Цикл//​ — это многократное повторение одной и той же группы операторов,​ возможно,​ с новыми значениями переменных,​ входящих в эту группу. +
- +
-Типичный пример цикла мы видим в "​Сказке о рыбаке и рыбке"​ А.С.Пушкина. Действия слабохарактерного старика повторялись //​циклически//:​  +
-<​diagram>​ +
-|разговор с золотой рыбкой| ──▶ +
-||!@4| +
-|путь от моря к старухе| ──▶  +
-||!@4| +
-|получение нового приказания от старухи и снова| ──▶ +
-||!@4| +
-|к морю,​| +
-||!@4| +
-|к золотой рыбке.| +
-</​diagram>​ +
- +
-Параметром цикла (в терминах языка BASIC) здесь выступает алчность старухи,​ которая увеличивается при каждом новом прохождении циклического участка. +
- +
-Программы,​ содержащие циклы, называются //​циклическими//​. +
- +
-Цикл, не содержащий внутри себя других циклов,​ называется //​простым//​. В противном случае его называют //​кратным//​ или //​вложенным//​. +
- +
-В школьном алгоритмическом языке для записи циклических алгоритмов применяются две конструкции:​ цикл "​__для__"​ и цикл "​__пока__"​. +
- +
-Рассмотрим,​ как на языке программирования [[msx:​basic:​]] программируется //цикл "​__для__"//​. +
- +
-Для этого существуют два специальных оператора:​ оператор начала цикла (оператор ''​FOR''​),​ оператор конца цикла (оператор ''​NEXT''​). Операторы ''​FOR''​ и ''​NEXT'',​ как правило(!),​ используются совместно. +
- +
-Оператор начала цикла (его называют ещё //​заголовком//​ цикла) имеет вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-FOR i = α TO β [ STEP γ ] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-Здесь:​ +
-  * ''​FOR''​ ("​для"​),​ ''​TO''​ ("​до"​),​ ''​STEP''​ ("​шаг"​),​ ''​NEXT''​ ("​следующий"​) — служебные слова;​ +
-  * i — имя числовой переменной (без индекса!);​ +
-  * α, β, γ — арифметические выражения. +
- +
-Вслед за оператором //​начала//​ цикла располагают операторы программы,​ которые должны выполняться циклически (эти операторы образуют //​тело//​ цикла). За последним оператором тела цикла размещается оператор //​конца//​ цикла, который имеет следующий синтаксис:​ +
-<​code>​ +
-NEXT [i] +
-</​code>​ +
-Обратите внимание на то, что переменная,​ указываемая после ''​NEXT'',​ должна быть той же переменной,​ которая упоминается в операторе начала цикла после служебного слова ''​FOR''​ (эту переменную называют //​параметром//​ цикла). +
- +
-Значения арифметических переменных α и β задают соответственно начальное и конечное значения параметру цикла. Значение арифметического выражения γ — это //шаг//, на величину которого изменяется параметр цикла после каждого повторения тела цикла. Шаг может быть как положительным,​ так и отрицательным. +
- +
-Если шаг цикла равен +1, указание ''​STEP γ''​ в операторе начала цикла может опускаться (говорят,​ что "по умолчанию шаг цикла равен 1"). +
- +
-Итак, в программе цикл "​__для__"​ записывается следующим образом:​ +
-<​code>​ +
-FOR i = α TO β [ STEP γ ] +
-     ​тело цикла +
-NEXT i +
-</​code>​ +
-Выполнение этого фрагмента программы происходит следующим образом:​ параметру цикла i присваивается его начальное значение (значение арифметического выражения α), и один раз выполняется тело цикла (т.е. группа операторов,​ размещённых между заголовком цикла и соответствующим оператором ''​NEXT''​). Вслед за этим оператор ''​NEXT''​ изменяет значение параметра цикла i на величину шага (значение арифметического выражения γ) и проверяет,​ не вышло ли новое значение параметра цикла из рабочего интервала (если шаг положителен,​ то не стало ли оно больше конечного значения параметра цикла (значения арифметического выражения β); если шаг отрицателен — не стало ли меньше конечного значения параметра цикла). +
- +
-Если этого не происходит,​ то осуществляется повторное выполнение тела цикла, в противном случае — //​выход//​ из цикла, то есть переход к оператору,​ следующему за ''​NEXT''​. +
- +
-Заметим,​ что при //​любых//​ значениях α, β, γ тело цикла будет выполнено //​хотя//​ бы //​один//​ раз (в отличие от школьного алгоритмического языка и других языков программирования!)! +
- +
-{{anchor:​e034-01}} __//​Пример//​__:​ \\ {{.examples:​034-01.bas|}} \\ [[+tab|wmsxbpge>​034-01.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 FOR A=1 TO 10 STEP-1 +
-20 PRINT A +
-30 NEXT A +
-run +
- 1 +
-Ok +
-</​code>​ +
-Эта программа выведет на экран только начальное значение параметра цикла A=1. При первой же встрече с оператором ''​NEXT''​ A будет обнаружено,​ что конечное значение параметра цикла (A=10) уже "​позади"​! +
- +
-Ещё раз обращаем Ваше внимание на то, что: +
-  * проверка на окончание цикла производится //​после//​ выполнения тела цикла;​ +
-  * изменение параметра цикла происходит //​перед//​ проверкой на окончание цикла. +
-Таким образом,​ следующие фрагменты эквивалентны:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
- … +
-10 FOR K=1 TO 4 STEP 2 +
- ​… ​  ​тело цикла ​ … +
-100 NEXT K +
- … +
- +
-</​code>​ +
-</​WRAP>​ +
- +
-<WRAP half column>​ +
-<​code>​ +
-  … +
-10 K=1 +
-20 '​Пустой оператор +
- ​… ​ тело цикла ​ … +
-100 K=K+2 +
-110 IF K≤4 GOTO 20 +
- … +
-</​code>​  +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Отметим,​ что оператор цикла ''​FOR…NEXT''​ можно располагать на одной программной строке. Это целесообразно делать,​ если тело цикла состоит из одного–двух операторов. Например:​ +
-\\ {{anchor:​e034-02}} {{.examples:​034-02.bas|}} \\ [[+tab|wmsxbpge>​034-02.bas]] +
-<​code>​ +
-10 FOR L=1 TO 10:PRINT L;L^3:NEXT L +
-</​code>​ +
-Выполнив эту строку,​ компьютер выведет на экран дисплея таблицу кубов чисел 1, 2, 3, …, 10. +
- +
-Кстати,​ сравните конструкцию ''​FOR…NEXT''​ с циклом "​__для__"​ в школьном алгоритмическом языке: \\ +
-__для__ x __от__ x<​sub>​min</​sub>​ __до__ x<​sub>​max</​sub>​ __шаг__ x<​sub>​шаг</​sub>​ \\ +
-│__нц__ \\ +
-│      серия ​ команд \\ +
-│__кц__ +
-   +
-Напомним,​ что в том месте дисплейной строки,​ где надо обратить Ваше внимание на наличие символа пробел (" "), мы будем использовать в тексте символ "​·"​. +
- +
-**//​Важное замечание!//​** \\ +
-Значения переменных α, β, γ можно изменять операторами,​ находящимися в теле цикла! Следующие две программы идентичны:​ +
-<WRAP group> +
-<WRAP half column>​ +
-{{anchor:​e034-031}} {{.examples:​034-031.bas|}} \\ [[+tab|wmsxbpge>​034-031.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 A=7:​B=9:​H=1 +
-20 FOR I=A TO B STEP H +
-30 A=4:​B=5:​H=2 +
-40 ? A;​B;​H:​NEXT +
-run +
-·4··5··2 +
-·4··5··2 +
-·4··5··2 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-{{anchor:​e034-032}} {{.examples:​034-032.bas|}} \\ [[+tab|wmsxbpge>​034-032.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 A=7:​B=9:​H=1:​A1=A:​B1=B:​H1=H +
-10 FOR I=A1 TO B1 STEP H1 +
-20 A=4:​B=5:​H=2 +
-25 ? A;​B;​H:​NEXT +
-run +
-·4··5··2 +
-·4··5··2 +
-·4··5··2 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Таким образом,​ текущие значения переменных α, β, γ (в теле цикла) могут не совпадать с начальным,​ конечным значениями параметра цикла и значением шага соответственно! +
- +
-В то же время, //​значения//​ α, β и γ, указанные в заголовке цикла, "​недоступны"​ для операторов тела цикла при условии,​ что в теле цикла нет обращения к заголовку цикла. +
- +
-{{anchor:​e034-04}} __//​Пример//​__:​ \\ {{.examples:​034-04.bas|}} \\ [[+tab|wmsxbpge>​034-04.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,H +
-20 FOR I=A TO B STEP H:?"​I=";​I +
-30 A=A+2:IF A<6 GOTO 20 ELSE ?A +
-40 NEXT:?I +
-run +
-? 2,3,1 +
-I= 2  +
-I= 4 +
- 6 +
- 5 +
-Ok +
-</​code>​ +
-Следовательно,​ изменить начальное и конечное значения параметра цикла, а также значение шага можно только(!) с помощью обращения к заголовку цикла. +
- +
-Таким образом,​ операторы,​ находящиеся в теле цикла могут управлять числом повторений цикла! +
- +
-Значение параметра цикла i также //​можно//​ изменять операторами,​ находящимися в теле цикла! +
- +
-По окончании работы цикла значение параметра цикла i равно первому его значению,​ для которого выполнилось неравенство +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-sign([β]-i)·[γ]<​0 +
-</​code>​ +
-</​WRAP>​ +
-(∗) +
- +
-+
-<WRAP half column>​ +
- +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-где обозначено:​ +
-  * [β] и [γ] — значения арифметических выражений β и γ соответственно;​ +
-  * функция sign(x)("​signum"​ — "​знак"​) определяется формулой:​ <​WRAP>​ +
- +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-        ⎧ 1, если x>0 +
-sgn(x)= ⎨ 0, если x=0 +
-        ⎩-1, если x<0 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-</​WRAP>​ +
- +
-Условие (∗) принято вместо условия ([β]-i)·[γ]<​0 потому,​ что при малых ([β]-i) и [γ] произведение ([β]-i)·[γ] может дать "​машинный нуль",​ хотя будет выполнено неравенство (∗)! +
- +
-Кстати,​ число повторений цикла "​без фокусов"​ можно вычислить по формуле:​ +
-  K=INT(ABS(([β]-[α])/​[γ]))+1 +
- +
-Отметим,​ что во многих других языках программирования (ALGOL, Fortran) по окончании цикла значение параметра i становится //​неопределённым//​. В этом случае им можно "​пользоваться"​ только после присвоения нового значения. +
- +
-__//​Примеры//​__:​ +
-  * {{anchor:​e034-05}} {{.examples:​034-05.bas|}} \\ [[+tab|wmsxbpge>​034-05.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,H +
-20 FOR I=A TO B STEP H +
-40    ?​I;:​I=I+1:?​I +
-50 NEXT +
-run +
-? 1,3,1 +
-·1··2 +
-·3··4 +
-Ok +
-</​code>​ +
-  * {{anchor:​e034-06}} {{.examples:​034-06.bas|}} \\ [[+tab|wmsxbpge>​034-06.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,H +
-20 FOR I=A TO B STEP H +
-30    H=H+1:​I=I+H:?​H;​I +
-40 NEXT +
-run +
-? 1,4,1 +
-·2··3 +
-·3··7 +
-Ok +
-</​code>​ +
-  * {{anchor:​e034-07}} {{.examples:​034-07.bas|}} \\ [[+tab|wmsxbpge>​034-07.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,H +
-20 FOR I=A TO B STEP H +
-30 NEXT I:PRINT I +
-run +
-? 4,5,2 +
- 6 +
-Ok +
-</​code>​ +
-  * {{anchor:​e034-08}} {{.examples:​034-08.bas|}} \\ [[+tab|wmsxbpge>​034-08.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,H +
-20 FOR I=A TO B STEP H +
-30 I=I^2:​NEXT:?​I +
-run +
-? 5,1,1 +
- 26 +
-Ok +
-</​code>​ +
- +
-Тело цикла по отношению к остальной части программы замкнуто,​ то есть //​нельзя//​ "​входить"​ в него, минуя заголовок цикла. +
- +
-Возможен досрочный выход из цикла не через его окончание,​ а с использованием операторов ''​IF…THEN…ELSE…''​ и ''​GOTO''​ (в этом случае говорят,​ что цикл выполняется "​n+1/​2"​ раз!). При этом значение параметра цикла //​определено//​ и равно тому значению,​ при котором произошёл выход из цикла. +
- +
-{{anchor:​e034-09}} __//​Пример//​__. Найти индекс первого положительного элемента одномерного числового массива А(N). \\ {{.examples:​034-09.bas|}} \\ [[+tab|wmsxbpge>​034-09.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT N,I:INPUT "​Введите N";N +
-20 DIM A(N)'​Описание массива А +
-30 FOR I=1 TO N:INPUT A(I):​NEXTI'​Ввод массива A +
-40 FOR I=1 TO N +
-50 IF A(I)>0 THEN ?"​Искомый индекс:";​I:​GOTO 60 ELSE NEXTI +
-60 PRINT"​We are out of the loop!" 'Мы вышли из цикла! +
-run +
-Введите N? 4 +
-? -1 +
-? -3 +
-? 5 +
-? -4 +
-Искомый индекс:​ 3 +
-We are out of the loop! +
-Ok +
-</​code>​ +
-Отметим,​ что оператор ''​GOTO 60''​ в 50 строке можно заменить на последовательность операторов:​ +
-<​code>​ +
-I=N:NEXT I +
-</​code>​ +
-(мы пользуемся тем, что параметр цикла I можно менять внутри цикла!),​ которая обеспечит в случае A(I)>0 выход из цикла. Обратите внимание на то, что можно даже выйти из тела цикла в "​окружающую"​ его часть программы,​ а затем вернуться снова в тело цикла, //​минуя//​ заголовок! +
- +
-{{anchor:​e034-10}} __//​Пример//​__. \\ {{.examples:​034-10.bas|}} \\ [[+tab|wmsxbpge>​034-10.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 FOR I=1 TO 5 +
-20 IF I≤2 THEN GOTO 100 +
-30 M=I^2:?M +
-40 NEXT I:END +
-100 I=I+3:GOTO 30 '​Возвращение в тело цикла! +
-run +
- 16 +
- 25 +
-Ok +
-</​code>​ +
- +
-Приведённый пример показывает,​ как, используя оператор ''​GOTO'',​ можно "​расширить"​ тело цикла, включив в него произвольные части программы. +
- +
-  - __//​Примеры простых циклов//​__ <​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-5% текста программы занимают 90% времени её выполнения.<​WRAP rightalign>​ +
-—//​Аксиома программирования//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-  * 1) <​WRAP>​ {{anchor:​e034-11}} {{.examples:​034-11.bas|}} \\ [[+tab|wmsxbpge>​034-11.bas]] <​code>​ +
-10 FOR I=1 TO 1000:NEXT '​Задержка ≈ 2.35 секунды +
-</​code>​ +
-Применение оператора цикла с "​пустым"​ телом позволяет получить эффект //​задержки//​ по //​времени//​. Запомните этот трюк! +
-</​WRAP>​ +
-  * 2) <​WRAP>​ {{anchor:​e034-12}} {{.examples:​034-12.bas|}} \\ [[+tab|wmsxbpge>​034-12.bas]] <​code>​ +
-Ok +
-10 '​Признание в любви! +
-20 INPUT"​Введите целое число N";​N% +
-30 FOR I%=1 TO N% +
-40    PRINT"​I love YOU!"​ +
-50 NEXT I% +
-</​code>​ +
-Думаем,​ что результат работы этой N–"​любвиобильной"​ программы Вас порадует. Заметим,​ что программа идентична алгоритму с использованием команды повторения n __раз__ в школьном алгоритмическом языке [[bibliography#​b13|[13]]]:​ \\ +
-__нц__ число повторений __раз__\\ +
-серия команд \\ +
-│ __кц__ \\ +
-так как тело цикла не зависит от параметра цикла. +
-</​WRAP>​ +
-  * 3) <​WRAP>​ {{anchor:​e034-131}} {{.examples:​034-131.bas|}} \\ [[+tab|wmsxbpge>​034-131.bas]] <​code>​ +
-Ok +
-10 DEFINT N,I:INPUT "​Введите N";N +
-20 DIM A(N) '​Массив А описан! +
-30 FOR I=0 TO N:INPUT A(I):NEXT I +
-40'​Данный фрагмент позволяет осуществить ввод элементов одномерного массива А (в массиве N+1 элемент!) +
-</​code>​ +
-Приведём ещё один способ решения указанной проблемы:​ +
-\\ {{anchor:​e034-132}} {{.examples:​034-132.bas|}} \\ [[+tab|wmsxbpge>​034-132.bas]] <​code>​ +
-Ok +
-10 DIM A(5) '​Массив A содержит 6 элементов! +
-20 DATA 1.,​2.,​3.,​4.,​5.,​6. +
-30 FOR I=0 TO 5:READ A(I):​NEXTI +
-</​code>​ +
-</​WRAP>​ +
-  * 4) <​WRAP>​ //​инициализация//​ массива (присвоение начальных значений) целыми псевдослучайными числами,​ принадлежащими отрезку [A,B]: +
-\\ {{anchor:​e034-14}} {{.examples:​034-14.bas|}} \\ [[+tab|wmsxbpge>​034-14.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT N,I,C:INPUT A,B,N:DIM C(N) +
-20 X=RND(-TIME) '​начальная установка генератора псевдослучайных чисел +
-30 FOR I=1 TO N +
-40 C(I)=INT((B-A+1)*RND(1)+A):?​C(I):​NEXTI +
-run +
-? -5,3,12 +
--1·-3··0·-1··0·-1·-3··3··2·-5··0··1 +
-Ok +
-</​code>​ +
-//​Замечание//​. Как можно чаще применяйте указанный способ инициализации массива псевдослучайными числами при //​тестировании//​ (процессе обнаружении ошибок) Ваших программ! +
-</​WRAP>​ +
-  * 5) {{anchor:​e034-15}} {{.examples:​034-15.bas|}} \\ [[+tab|wmsxbpge>​034-15.bas]] <​code>​ +
-NEW +
-Ok +
-10 '​Табулирование функции y=exp(sin(x)) на [A,B] с шагом H. +
-100 INPUT A,B,H +
-110 FOR X=A TO B STEP H +
-120 ?​USING"#​.### ​ #​.###";​X;​EXP(SIN(X)) +
-130 NEXT +
-run +
-? .0,1.,.2 +
-0.000  1.000 +
-0.200  1.220 +
-0.400  1.476 +
-0.600  1.759 +
-0.800  2.049 +
-1.000  2.320 +
-Ok +
-</​code>​ +
-  * 6) <​WRAP>​ составить программу табулирования функции y=sinx на отрезке [a,b], причём на первой половине отрезка — с шагом h, a на второй половине отрезка — с шагом h/2. +
- +
-Приведённые ниже программы эквивалентны и дают полное представление о работе оператора ''​FOR…NEXT''​. +
-  * 6.1) {{anchor:​e034-161}} {{.examples:​034-161.bas|}} \\ [[+tab|wmsxbpge>​034-161.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,H:P=0 +
-20 FOR X=A TO B STEP H +
-30 IF X>​=(A+B)/​2ANDP=0 THEN P=1:​A=(A+B)/​2:​H=H/​2:​GOTO 20 +
-35 PRINT X;SIN(X) +
-40 NEXT X +
-run +
-? 0,1,.1 +
- ​0 ​ 0 +
-.1  .099833416646831 +
-.2  .19866933079507 +
-    …         … +
-.95  .81341550478941 +
- ​1 ​ .84147098480792 +
-Ok +
-</​code>​ +
-  * 6.2) {{anchor:​e034-162}} {{.examples:​034-162.bas|}} \\ [[+tab|wmsxbpge>​034-162.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,​B,​H:​P=0'​Р-флажок! +
-20 A1=A:​B1=B:​H1=H +
-25 X=A1 +
-30 IF X>​=(A+B)/​2ANDP=0 THEN P=1:​A=(A+B)/​2:​H=H/​2:​GOTO 20 +
-35 PRINT X;SIN(X) +
-40 X=X+H1:IF X≤B1 GOTO 30 +
-</​code>​ +
-  * 6.3) {{anchor:​e034-163}} {{.examples:​034-163.bas|}} \\ [[+tab|wmsxbpge>​034-163.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT A,​B,​H:​P=0:​X=A +
-20 IF X>​=(A+B)/​2 THEN FOR X=(A+B)/​2+H/​2 TO B STEP H/2:P=1 ELSE FOR X=A TO (A+B)/2 STEP H +
-30 PRINT X;SIN(X) +
-40 NEXT:IF P=0 THEN GOTO 20 +
-</​code>​ +
-</​WRAP>​ +
-  * 7) <​WRAP>​ пусть требуется вычислить значение функции y=x₂ для x=0, 0.1, 0.2,…, 1., кроме x=0.3. +
-Предостережём от //​неверного//​ (в принципе!) решения:​ +
-\\ {{anchor:​e034-171}} {{.examples:​034-171.bas|}} \\ [[+tab|wmsxbpge>​034-171.bas]] +
-<​code>​ +
-10 FOR X=0 TO 1 STEP 0.1 +
-20 IF X><​0.3 THEN ?X;X^2:NEXT X ELSE NEXT X +
-</​code>​ +
-Значение шага цикла (0.1) есть десятичная константа с фиксированной точкой. Поэтому,​ вследствие накопления погрешности округления,​ мало надежды (хотя она и есть!) на то, что на четвёртом цикле значение X будет точно равно 0.3. Да и на одиннадцатом цикле значение X может оказаться "​чуточку"​ большим (меньшим) единицы! +
- +
-Поэтому верное решение будет, например,​ таким:​ +
-\\ {{anchor:​e034-172}} {{.examples:​034-172.bas|}} \\ [[+tab|wmsxbpge>​034-172.bas]] +
-<​code>​ +
-10 FOR Y%=0 TO 10 +
-20 IF Y%><3 THEN X=Y%/​10:?​X;​X^2:​NEXT Y% ELSE NEXT Y% +
-</​code>​ +
-</​WRAP>​ +
-  * 8) {{anchor:​e034-18}} {{.examples:​034-18.bas|}} \\ [[+tab|wmsxbpge>​034-18.bas]] <​code>​ +
-NEW +
-Ok +
-5 '​Вычисление значения многочлена A(0)+A(1)·x+A(2)·x₂+···+A(n)·xⁿ в точке x=X0 по схеме Горнера +
-10 INPUT"​Введите степень многочлена n=";​N:​INPUT "​X0=";​X +
-20 FOR I=0 TO N:​PRINT"​A("​I"​)=";:​INPUT A(I):​NEXTI +
-36 C=A(N) +
-40 FOR I=N-1 TO 0 STEP -1:​C=C*X+A(I):​NEXTI:​PRINT "​c=";​C +
-</​code>​ +
-  * 9) <​WRAP>​ последовательность чисел Фибоначчи <​m>​F(1),​ F(2),..., F(n),​...</​m>​ +
-определяется по следующим рекуррентным формулам:​ <​m>​F(1)=1,​ F(2)=1, F(n+2)=F(n)+F(n+1),​ n=1,​2,​...</​m>​ . +
- +
-Напишите программу,​ вычисляющую <​m>​F(N)</​m>​ по заданному <​m>​N</​m>​. +
-\\ {{anchor:​e034-191}} {{.examples:​034-191.bas|}} \\ [[+tab|wmsxbpge>​034-191.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT N,I:INPUT N:A=1:B=1 +
-20 IF N=1ORN=2 THEN C=1:? C:END +
-30 FOR I=1 TO N-2:​C=A+B:​A=B:​B=C:​NEXT +
-35 PRINT C:END +
-run +
-? 5 +
- 5 +
-Ok +
- +
-run +
-? 10 +
- 55 +
-Ok +
- +
-run +
-? 100 +
- ​3.5422484817927E+20 +
-Ok +
-</​code>​ +
- +
-Известно,​ что для членов последовательности Фибоначчи имеет место красивая формула:​ \\  +
-<​m>​F(n)=1/​sqrt{5}delim{[}{ ({1+sqrt{5}}/​2)^n - ({1-sqrt{5}}/​2)^n }{]}, n=1,2, ...</​m>​ \\  +
-Используем её для написания второго варианта предыдущей программы:​ +
-{{anchor:​e034-192}} {{.examples:​034-192.bas|}} \\ [[+tab|wmsxbpge>​034-192.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 FOR N=1 TO 63 +
-20    A=FIX((((1+SQR(5))/​2)^N-((1-SQR(5))/​2)^N)/​SQR(5)+0.5) +
-30    PRINT"​n=";​N;"​A=";​A +
-40 NEXT +
-run +
-n= 1  A= 1 +
-   … +
-n= 63  A= 6557470319842 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-Как уже говорилось,​ тело цикла может содержать второй цикл — //​внутренний//​ по отношению к первому,​ //​внешнему//​ циклу ("​бумажные стаканчики"​). Внутренний цикл должен целиком содержаться в теле внешнего цикла. Таким образом,​ оператор ''​NEXT''​ для внутреннего цикла должен стоять перед оператором ''​NEXT''​ внешнего цикла. Нарушение этого правила приводит к появлению на экране сообщения об ошибке:​ <WRAP centeralign>"​NEXT without FOR in ..." \\ (//"​Оператор NEXT без оператора FOR в строке …"//​).</​WRAP>​ +
- +
-{{anchor:​e034-20}} __//​Пример//​__. \\ {{.examples:​034-20.bas|}} \\ [[+tab|wmsxbpge>​034-20.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 FOR I=1 TO 3:FOR J=2 TO 4 +
-20 IF J>1 THEN NEXT I +
-30 NEXT J +
-run +
-NEXT without FOR in 30 +
-Ok +
-</​code>​ +
-Тело внутреннего цикла в свою очередь может содержать ещё один цикл, внутренний по отношению к нему и так далее. Интерпретатор [[msx:​basic:​]] устанавливает максимальную "​глубину"​ (число) вложений циклов,​ однако она настолько велика,​ что превысить её практически невозможно! +
- +
-Учтите,​ что каждый оператор ''​FOR…NEXT''​ занимает при работе 25 байтов //​стека//,​ причём стек освобождается только при завершении цикла, после последнего выполнения оператора ''​NEXT''​! +
- +
-Тем не менее, если программа использует слишком много циклов одновременно,​ может возникнуть сообщение об ошибке:​ <WRAP centeralign>"​Out of memory"​ \\ (//"​Выход за пределы памяти"//​).</​WRAP>​ +
- +
-Если требуется,​ чтобы несколько вложенных операторов ''​FOR''​ заканчивались в одном месте, можно использовать один оператор ''​NEXT'',​ содержащий список параметров циклов,​ разделённых запятыми:​ первое имя в списке соответствует самому внутреннему,​ последнее — самому внешнему циклу. +
-</​WRAP>​ +
-  - __//​Примеры вложенных циклов//​__ <​WRAP>​ +
- +
-  * 1) {{anchor:​e034-21}} {{.examples:​034-21.bas|}} \\ [[+tab|wmsxbpge>​034-21.bas]]<​code>​ +
-Ok +
-10 FOR X=1 TO 100 +
-20 FOR Y=1 TO  10 +
-30 ? "1000 раз"​ +
-40 NEXT Y +
-50 ? "​Только 100 раз"​ +
-60 NEXT X +
-</​code>​ +
-  * 2) {{anchor:​e034-22}} {{.examples:​034-22.bas|}} \\ [[+tab|wmsxbpge>​034-22.bas]] <​code>​ +
-Ok +
-10 '​Инициализация диагональной (единичной) матрицы X(3,3) +
-20 FOR I=1 TO 3:FOR J=1 TO 3 +
-30 X(I,​J)=INT(I/​J)*INT(J/​I) +
-40 NEXT J +
-50 NEXT I +
-</​code>​ +
-  * 3)<​WRAP>​ {{anchor:​e034-23}} {{.examples:​034-23.bas|}} \\ [[+tab|wmsxbpge>​034-23.bas]] <​code>​ +
-10 '​Ввод двумерного массива MAS по столбцам +
-20 DIM MAS(30,​20):​FOR I=1 TO 20:FOR J=1 TO 30 +
-30 INPUT MAS(J,I):? MAS(J,​I):​NEXT J,I +
-</​code>​ +
-Оператор ''?​ MAS(J,​I)''​ позволяет осуществить контроль вводимой информации. Вопрос к читателю:​ что необходимо изменить в приведённом фрагменте,​ если Вы пожелаете ввести массив MAS по строкам?​ +
-</​WRAP>​ +
-  * 4)<​WRAP>​ {{anchor:​e034-24}} {{.examples:​034-24.bas|}} \\ [[+tab|wmsxbpge>​034-24.bas]] <​code>​ +
-Ok +
-5'​Проверка результатов логических операций NOT,​AND,​OR,​XOR,​EQV,​IMP для операндов i, j∈-{-1,​0}. +
-10 FOR I=-1 TO 0:FOR J=-1 TO 0 +
-20 PRINT I;​J;​NOT(I);​IANDJ;​IORJ;​IXORJ;​IEQVJ;​IIMPJ +
-40 NEXT:NEXT +
-run +
--1 -1  0 -1 -1  0 -1 -1 +
--1  0  0  0 -1 -1  0  0 +
- 0 -1 -1  0 -1 -1  0 -1 +
- ​0 ​ 0 -1  0  0  0 -1 -1 +
-Ok +
-</​code>​ +
-Сравните полученные результаты с таблицей,​ приведённой ранее в [[01#I.7.2. Операции отношения. Логические операции|разделе I.7.2]].</​WRAP>​ +
-  * 5) {{anchor:​e034-25}} {{.examples:​034-25.bas|}} \\ [[+tab|wmsxbpge>​034-25.bas]] <​code>​ +
-NEW +
-Ok +
-5'"​Удобный"​ вывод на экран двумерного массива. +
-10 FOR I=1 TO 3:FOR J=1 TO 4:READ A(I,​J):​NEXTJ,​I +
-15 FOR I=1 TO 3:FOR J=1 TO 4 +
-20 '​Обратите внимание на символ ";"​ в строке 25! +
-25 PRINT A(I,​J);:​NEXT J:​PRINT:​NEXT I +
-30 DATA 1,​2,​3,​4,​3,​4,​5,​6,​0,​4,​5,​3 +
-run +
- ​1 ​ 2  3  4 +
- ​3 ​ 4  5  6 +
- ​0 ​ 4  5  3 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-Операторы ''​FOR''​ и ''​NEXT'',​ как правило,​ должны идти в паре и быть согласованы друг с другом. Если оператор ''​NEXT''​ выполняется раньше оператора ''​FOR''​ с тем же параметром цикла, то при выполнении такого ''​NEXT''​ выдаётся сообщение об ошибке:​ <WRAP centeralign>"​NEXT without FOR" ​ \\ //​("​Нет оператора FOR для данного NEXT"//​).</​WRAP>​ +
- +
-Оператор ''​FOR…NEXT''​ — единственный способ в [[msx:​basic:​]] для изменения естественного порядка выполнения операторов без задания номеров программных строк, на которые нужно перейти. +
- +
-Весьма поучительно сопоставить конструкцию ''​FOR…NEXT''​ с конструкцией цикла "​__пока__"​ в школьном алгоритмическом языке: \\ +
-__пока__ условие \\ +
- ​__нц__ \\ +
-│      серия команд \\ +
-│__кц__ +
- +
-Отметим,​ что в некоторых версиях BASIC (например,​ для персональных компьютерах фирмы IBM: IBM PC, IBM PC/XT, IBM PCjr) существует конструкция,​ почти до словно повторяющая цикл "​__пока__";​ её структура([[bibliography#​b11|[11],​ с.74]]): +
-<​code>​ +
-WHILE  условие STEP 0 +
-  тело цикла +
-WEND +
-</​code>​ +
-здесь ''​WHILE''​ ("​while"​ — "​пока"​),​ ''​WEND''​ ("​конец цикла WHILE"​) — служебные слова. +
- +
-Оператор цикла ''​WHILE''​ повторяет выполнение операторов тела цикла до тех пор, пока выполняется требуемое условие. Если условие не истинно или становится не истинным,​ операторы тела цикла не выполняются ни разу, и управление передаётся первому оператору,​ следующему за ''​WEND''​. +
- +
-Обратите внимание на то, что если условие оказывается ложным (не удовлетворяется при первой же проверке),​то операторы тела цикла вообще не выполняются! +
- +
-Как правило,​ условие в операторе цикла ''​WHILE…WEND''​ должно когда–нибудь стать ложным,​ иначе повторение будет бесконечным. Впрочем,​ если Ваша программа вошла в бесконечный цикл или каким–нибудь другим образом вышла из–под Вашего контроля,​ //не паникуйте//​! В [[msx:​basic:​]] предусмотрена возможность //​прерывания//​ программы — одновременным нажатием на две клавиши <​key>​CTRL+STOP</​key>​. +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Метод решения хорош, если с самого начала мы можем предвидеть — и далее +
-подтвердить это, — что, следуя этому методу,​ мы достигнем цели. +
-<WRAP rightalign>​ +
-—//​Г.В.Лейбниц//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Истина всегда оказывается проще, чем можно было предположить.<​WRAP rightalign>​ +
-—//​Р.Фейнман//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Попытаемся циклом ''​FOR…NEXT''​(!) описать цикл "​__пока__"​. Следующая весьма нетривиальная конструкция позволяет это сделать:​ +
-<​code>​ +
-   … +
-10 IF NOT условие THEN 60'​Если условие ложно,​то в цикл не входим! +
-20 FOR I=1 TO 0 STEP 1 '​Оригинальный заголовок цикла, не правда ли? +
-30   ​тело цикла +
-40   I = условие '​Потрясающе! Если условие ложно, то I=0, и цикл заканчивается;​ если условие истинно,​то I=-1, и мы продолжим выполнение тела цикла. +
-50 NEXT I +
-60 … '​Продолжение программы. +
-</​code>​ +
-Если в операторе ''​IF''​ использовать указатель шага цикла ''​STEP 0'',​ то цикл будет бесконечным. //​Иногда//​(?​) это бывает полезным! +
- +
- +
-{{anchor:​e034-31}} __//​Пример 1//__. \\ {{.examples:​034-31.bas|}} \\ [[+tab|wmsxbpge>​034-31.bas]] \\ Вычислить сумму вида: <​m>​S=sum{n=1}{k}{n}</​m>​ +
- +
-<​code>​ +
-Ok +
-5  DEFINT K,​N,​I,​S:​INPUT K:S=0:N=1 +
-20 IF N>K THEN 70 +
-30 FOR I=1 TO 0 STEP 1 +
-40 S=S+N:N=N+1 'Т е л о  ц и к л а +
-50 I=N≤K +
-60 NEXT I +
-70 PRINT S;"​Тестовый пример:";​K*(K+1)/​2 +
-run +
-? 100 +
-5050 Тестовый пример:​ 5050 +
-Оk +
-</​code>​ +
- +
-Ясно,​что в приведённой программе можно применить оператор цикла ''​FOR…NEXT'',​ поэтому рассмотрим пример,​ где использование оператора цикла ''​FOR…NEXT''​ не помогает. +
- +
-{{anchor:​e034-32}} __//​Пример 2//__. \\ {{.examples:​034-32.bas|}} \\ [[+tab|wmsxbpge>​034-32.bas]] \\ Пусть для данного положительного числа <​m>​S</​m>​ требуется найти наибольшее натуральное <​m>​K</​m>,​ такое, что <m>S >= 1^2 + 2^2 + ... + K^</​m>​. +
- +
-<​code>​ +
-Ok +
-10 DEFINT I,J:INPUT S:J=0 +
-20 IF S≤0 THEN PRINT"​S неположительно!":​END +
-30 FOR I=1 TO 0 STEP 1 +
-40 J=J+1:​S=S-J^2 +
-50 I=S>=0 +
-60 NEXT I +
-70 PRINT J-1:END +
-run +
-? 23 +
- 3 +
-Ok +
- +
-run +
-? 300 +
-+
-Ok +
-</​code>​ +
-Из сопоставления примеров 1 и 2 ясно, что цикл "​__для__"​ используется,​ как правило,​ когда количество исполнения цикла известно заранее. Если же число исполнений определить нельзя,​ если цикл должен быть прерван не по достижению параметром цикла конечного значения,​а по какому–то другому условию (в примере 2: <m>S <= 1^2 + 2^2 + ... + k^2</​m>​),​ необходим цикл "​__пока__"​. +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Прежде чем решать задачу,​ подумай,​ что делать с её решением. +
-<WRAP rightalign>​ +
-—//​Р.Хемминг//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-В науке часто недостаточно решить какую–нибудь задачу или группу задач. После этого нужно присмотреться к этим задачам и заново осмыслить,​ какие же вы задачи решили. Нередко,​ решая одну задачу,​мы автоматически находим ответ и на другой вопрос,​ о котором раньше вовсе не думали. +
-<WRAP rightalign>​ +
-—//​Н.Винер//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​e034-33}} __//​Пример 3//__. \\ {{.examples:​034-33.bas|}} \\ [[+tab|wmsxbpge>​034-33.bas]] \\ Составить программу нахождения суммы возрастающей арифметической прогрессии. +
-<​code>​ +
-NEW +
-Ok +
-5 DEFINT I:INPUT A1,​AN,​D'​А1-первый член арифметической прогрессии;​АN-последний ее член;​D-знаменатель (D>0!) +
-7 IF D<0 OR A1>AN THEN ?"​Прогрессия должна быть возрастающей! Повторите ввод!":​GOTO 5 +
-10 S=0:N=A1 +
-20 IF N>AN THEN GOTO 70 +
-30 FOR I=1 TO 0 STEP 1 +
-40 S=S+N:N=N+D '​Тело цикла +
-50 I=N<​=AN +
-60 NEXT I +
-70 ? S;"​Тестовый пример:";​((AN-A1)/​D+1)*(A1+D/​2*(AN-A1)/​D) +
-run +
-? 1,20,1 +
-210 Тестовый пример:​ 210 +
-Оk +
-run +
-? 20,2,1 +
-Прогрессия должна быть возрастающей! Повторите ввод! +
-?  … +
-</​code>​ +
- +
-Другой способ программирования на языке программирования [[msx:​basic:​]] цикла ''​WHILE…WEND''​ предполагает использование //"​опасного"//​ оператора ''​GOTO'':​ +
-<​code>​ +
-10 GOTO 100 +
-20 операторы ​   тела цикла +
-100 IF  условие ​ THEN GOTO 20 +
-</​code>​ +
- +
-Если количество операторов тела цикла невелико,​ то допустима следующая конструкция:​ +
-<​code>​ +
-10 IF  условие ​ THEN операторы ​   тела цикла:​ +
-GOTO 10 ELSE продолжение программы … +
-</​code>​ +
-Если же количество операторов цикла велико,​ то можно операторы тела цикла поместить в подпрограмму (см. [[04#IV.4. Подпрограммы|раздел IV.4.]]), вызываемую оператором ''​GOSUB'':​ +
-<​code>​ +
-10 IF условие THEN GOSUB 1000:GOTO 10 ELSE продолжение программы +
-               … +
-1000 Тело цикла +
-               … +
-1200 RETURN +
-</​code>​ +
- +
-__// Пример 4//__. Вычислить сумму S знакочередующегося числового ряда: +
-<​m>​sum{n=1}{infty}{ (-1)^n/n^2 }</m> с точностью E. +
- +
-Приведём три варианта программы:​ +
-  * 4.1) {{anchor:​e034-341}} {{.examples:​034-341.bas|}} \\ [[+tab|wmsxbpge>​034-341.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT E +
-20 S=0:​N=1:​A=(-1)^N/​N^2 +
-30 GOTO 50 +
-40 S=S+A:​N=N+1:​A=(-1)^N/​N^2 +
-50 IF ABS(A)>​=E THEN GOTO 40 +
-60 PRINT "​Результат:";​S +
-run +
-? .00001 +
-Результат:​-.82246204205923 +
-Ok +
-</​code>​ +
-  * 4.2) {{anchor:​e034-342}} {{.examples:​034-342.bas|}} \\ [[+tab|wmsxbpge>​034-342.bas]] <​code>​ +
-NEW +
-Ok +
-10 DEFINT I:INPUT E +
-20 FOR I=1 TO SQR(1/E) +
-30 S=S+(-1)^I/​I^2 +
-40 NEXT I +
-50 PRINT S +
-60 END +
-run +
-? .00001 +
--.82246204205923 +
-Ok +
-</​code>​ +
-  * 4.3) {{anchor:​e034-343}} {{.examples:​034-343.bas|}} \\ [[+tab|wmsxbpge>​034-343.bas]] <​code>​ +
-NEW +
-Ok +
-10 INPUT E +
-20 S=0:​N=1:​A=(-1)^N/​N^2 +
-30 IF ABS(A)>​=E THEN S=S+A:​N=N+1:​A=(-1)^N/​N^2:​GOTO 30 ELSE PRINT "​Результат:";​S:​PRINT"​Контроль:";​-(4*ATN(1))^2/​12:​PRINT"​Количество повторений цикла:";​N-1 '​Напомним,​ что значение π совпадает с 4*ATN(1) +
-run +
-? .1 +
-Результат:​-.86111111111111 +
-Контроль:​ -.82246703342412 +
-Количество повторений цикла: 3 +
-Оk +
- +
-run +
-? .01 +
-Результат:​-.81796217561099 +
-Контроль:​ -.82246703342412 +
-Количество повторений цикла: 10 +
-Ok +
- +
-run +
-? .001 +
-Результат:​-.82297055860543 +
-Контроль:​ -.82246703342412 +
-Количество повторений цикла: 31 +
-Ок +
-</​code>​ +
-Для проверки работоспособности программы мы воспользовались //​тестовым//​ примером на основе известного математического результата:​ <​m>​sum{n=1}{infty}{ (-1)^n/n^2 }=-pi^2/​12</​m>​. +
- +
-Наконец,​ отметим,​ что в данном примере количество повторений цикла существенно зависит от значения переменной E (однако,​ заранее количество повторений цикла нам неизвестно!). +
- +
-{{anchor:​e034-35}} __//​Пример 5//__. \\ Написать программу для вычисления <​m>​root{n}{A}</​m>​ , используя итерационную формулу Ньютона:​ \\ X(0)=A; X(k+1)=X(k)+(A/​X(k)^(n-1)-X(k))/​n,​ k=1,2,… +
-<​m>​X(0)=A;​ X(k+1)=X(k)+(A/​X(k)^(n-1)-X(k))/​n,​ k=1,​2,​...</​m>​ +
- +
-Вычисления продолжать до тех пор, пока <​m>​delim{|}{ X(k+1)-X(k)} {|}<​E</​m>,​ где <​m>​E>​0</​m>​ — заданное число (впрочем,​ возможен другой вариант "​останова"​ вычислений по выполнению условия <​m>​delim{|}{ X(K)^N-A }{|}<​E</​m>​). +
-\\ {{.examples:​034-35.bas|}} \\ [[+tab|wmsxbpge>​034-35.bas]] +
-<​code>​ +
-Ok +
-10 DEFINT N:INPUT N,A,E +
-20 IF A<​0ANDNMOD2=0 THEN ?"​Арифметический корень четной степени из отрицательного числа не существует":​END +
-30 X=A:​Y=X+(X/​A^(N-1)-X)/​N:​GOTO 50 +
-40 X=Y:​Y=X+(A/​X^(N-1)-X)/​N +
-50 IF ABS(Y-X)>​=E THEN GOTO 40 ELSE ? "​Результат:";​Y +
-run +
-? 2,​12,​0.001 +
-Результат:​ 3.4641016533502 +
-Ok +
-</​code>​ +
-А теперь — проверка:​ +
-<​code>​ +
-Ok +
-print SQR(12) +
-3.4641016151377 +
-Ok  +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-…Поверил\\  +
-Я алгеброй гармонию. +
-<WRAP rightalign>​ +
-—//​А.С.Пушкин. Моцарт и Сальери//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Обратимся теперь к лирике. Вот стихотворение Л.Мартынова (речь в нем идёт о девушке):​ +
-<WRAP group 99%> +
-<WRAP half column><​WRAP justify>​ +
-Кто геометрическое среднее между атомом и Солнцем?​ \\ +
-Ты, первое и последнее воплощение красоты. \\ +
-Не имеющая представления о строении вещества,​ \\ +
-слушающая в изумлении эти непонятные слова. \\ +
-Неспособная принять их к сведению,​будучи ужасно молодой. \\ +
-Вот ведь, какова ты, нечто среднее между атомом и звездой. +
-</​WRAP>​ +
-<WRAP half column></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Проверим,​ прав ли поэт. Масса атома водорода Ма=1.67E-27 кг, масса Солнца Mс=1.99E+30 кг.Их произведение найдём в режиме непосредственного выполнения команд:​ +
-<​code>​ +
-print 1.67E-27*1.99E+30 +
-3323.3 +
-Ok +
-</​code>​ +
-Поэт утверждает,​ что масса девушки (в кг) равна квадратному корню из числа 3323.3 . А тогда, используя ранее написанную программу,​ получим:​ +
-<​code>​ +
-run +
-? 2,​3323.3,​.001 +
-            ▲ +
-            │ +
- с точностью до грамма! +
-Результат:​ 57.648070219218 +
-Ок +
-</​code>​ +
- +
-Результат вполне правдоподобен:​ вес девушки ≈ 58 кг. +
- +
-===== III.5. Примеры ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Бросая в воду камешки,​ смотри на круги, ими образуемые:​ +
-иначе твоё занятие будет простой забавой. +
-<WRAP rightalign>​ +
-—//​Козьма Прутков//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Если я и открыл некоторые новые истины в науках,​ то я могу утверждать,​ что все они либо являются прямыми следствиями пяти или шести главных задач, которые мне удалось решить,​ либо зависят от них; я рассматриваю их как такое же число сражений,​ в которых военное счастье было на моей стороне. +
-<WRAP rightalign>​ +
-—//​Рене Декарт//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-В заключение рассмотрим несколько,​ на наш взгляд,​ интересных примеров. Разумеется,​ некоторые из приведённых ниже программ не являются оптимальными по времени выполнения и по занимаемой памяти. Однако,​ есть ещё одна величина,​ которую надо принимать в расчёт при оптимизации программы. Это — //​время//​ программиста. Программа,​ требующая много времени на написание и отладку,​может оказаться очень дорогой,​ даже если она расходует меньше машинного времени и занимает меньше места в памяти,​ чем какая–то другая,​ в целом эквивалентная ей программа. По этой причине распространена практика написания простых и понятных,​ но относительно медленных программ (для них имеется жаргонное выражение "quick and dirty programs"​ – "​скорые,​ но грязные программы"​). +
- +
-Если программу предлагается выполнить всего один–два раза, или если её придётся часто модифицировать,​ метод "​скорых,​ но грязных программ"​ почти всегда даёт наилучшие результаты! +
- +
-{{anchor:​e03-01}} __//​Пример 1//__. Найти наибольший элемент в одномерном массиве A(N), не пользуясь оператором ''​IF''​(!). +
-\\ {{.examples:​03-01.bas|}} \\ [[+tab|wmsxbpge>​03-01.bas]] +
-<​code>​ +
-Ok +
-10 DEFINT I,J,N:INPUT N:DIM A(N):​X=RND(-TIME):​FOR I=1 TO N:​A(I)=INT(40*RND(1)):​PRINT A(I);:​NEXT:​M=1:​PRINT +
-20 FOR I=1 TO N-1:FOR J=I+1 TO N +
-30 Y=-((A(I)>​A(J))*A(I))-(A(I)<​=A(J))*A(J):​M=-(Y>​M)*Y-(Y<​=M)*M:​NEXT J: +
-NEXT I:​PRINT"​Наибольший элемент:";​M +
-run +
-? 6 +
- ​28 ​ 33  7  32  28  20 +
-Наибольший элемент:​ 33 +
-Ok +
-</​code>​ +
-{{anchor:​e03-02}} __//​Пример 2//__. Написать программу,​ которая для введённой пользователем суммы печатает способ выдачи этой суммы наименьшим числом монет (имеются монеты 1,​2,​3,​5,​10,​15 и 20 копеек). +
-\\ {{.examples:​03-02.bas|}} \\ [[+tab|wmsxbpge>​03-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-20 DATA 20,​15,​10,​5,​3,​2,​1 +
-30 PRINT "​Введите сумму в копейках"​ +
-40 DEFINT S,I:INPUT S +
-50 IF S<>​INT(S) OR S<1 THEN 20 ELSE PRINT"​Разменяю-"​ +
-70 FOR I=1 TO 7:READ M:​K=INT(S/​M) +
-100 IF K>0 THEN PRINT K;"​раз";​M;"​коп.":​S=S-K*M ELSE S=S-K*M +
-120 NEXT I:END +
-run +
-Введите сумму в копейках +
-? 105 +
- ​Разменяю- +
- 5 раз 20 коп. +
- 1 раз 5 коп. +
-Оk +
- +
-run +
-Введите сумму в копейках +
-? 555 +
- ​Разменяю- +
- 27 раз 20 коп. +
- 1 раз 15 коп. +
-Ok +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Каждая решённая мною задача становилась образцом,​ который служил впоследствии для решения других задач. +
-<WRAP rightalign>​ +
-—//​Рене Декарт. Рассуждения о методе//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-…создаётся впечатление,​ что можно построить целый курс программирования,​ выбирая примеры только из задач сортировки. +
-<WRAP rightalign>​ +
-—//​Н.Вирт//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​e03-03}} __//​Пример 3//__. Напишите программу,​ располагающую массив слов на английском языке по алфавиту (выполняющую лексикографическое упорядочение) методом //​обменной сортировки//​ (методом "​пузырька"​). +
-\\ {{.examples:​03-03.bas|}} \\ [[+tab|wmsxbpge>​03-03.bas]] +
-<​code>​ +
-Ok +
-10 DEFINT N,I,J:INPUT "​Количество слов";​N +
-20 DIM A$(N) +
-30 FOR I=1 TO N:INPUT A$(I):​NEXT +
-40 FOR I=1 TO N-1:FOR J=I+1 TO N +
-50 IF A$(I)<​=A$(J) THEN 60 ELSE SWAP A$(I),​A$(J) +
-60 NEXT:NEXT +
-70 FOR I=1 TO N:PRINT A$(I):​NEXT +
-run +
-Количество слов? 5 +
-? Sedov +
-? Filippov +
-? Sokolova +
-? Shvetski +
-? Sedova +
-Filippov +
-Sedov +
-Sedova +
-Shvetski +
-Sokolova +
-Ok +
- +
-run +
-Количество слов? 5 +
-? Седов +
-? Филиппов +
-? Соколова +
-? Швецкий +
-? Седова +
-Филиппов +
-Седов +
-Седова +
-Соколова +
-Швецкий +
-Ok +
-</​code>​ +
- +
-Заметим,​что коды ASCII букв русского алфавита не упорядочены в соответствии с алфавитом (например,​ не соблюдено условие "​ВОВА"<"​ГЕНА"​),​ так как в компьютере буква "​В"​ следует за буквой "​Г"​ — в соответствии с латинскими буквами W и G, поэтому вышеприведённая программа не работает для слов, записанных русскими буквами! +
- +
-Следует отметить,​ что новый стандарт на отечественные персональные компьютеры,​ принятый в конце 1986 года, кардинально решает проблему – в нем коды русских букв возрастают в строгом соответствии с алфавитом (лексикографически упорядочены),​ и сортировка строковых переменных ничем не отличается от аналогичной процедуры над числовыми переменными. Но компьютеров с подобным кодированием русского алфавита,​ к сожалению,​ пока (1990 г.) очень мало! +
- +
-{{anchor:​e03-04}} __//​Пример 4//__. +
-\\ {{.examples:​03-04.bas|}} \\ [[+tab|wmsxbpge>​03-04.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 '​Сортировка с применением индекса. +
-11 '​Вместо переупорядочения самих значений в процессе сортировки можно образовать вспомогательный массив индексов,​ в котором отмечаются правильные места значений в массиве. +
-12 'Во время сортировки значения остаются на исходных местах,​ а изменяется лишь массив индексов. По окончанию сортировки массив индексов используется для копирования сортируемых значений в новый массив или служит справочником для работы с исходным массивом. +
-20 INPUT N:DIM A(N),I(N) +
-30  FOR M=1 TO N:INPUT A(M):NEXT M +
-40  FOR L=1 TO N:​I(L)=L:​NEXT +
-1000 '​Фрагмент пузырьковой сортировки. +
-1040 FOR M=N TO 2 STEP -1 +
-1050    FOR J=1 TO M-1 +
-1052       ​I1=I(J):​I2=I(J+1) +
-1060       IF A(I1)>​=A(I2) THEN 1100 +
-1070       ​I(J)=I2:​I(J+1)=I1 +
-1100    NEXT J +
-1110 NEXT M +
-1120 FOR L=1 TO N:​I1=I(L):​PRINT A(I1);:NEXT L +
-run +
-? 4 +
-? 56 +
-? 34 +
-? 87 +
-? 6 +
- ​87 ​ 56  34  6  +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-05}} __//​Пример 5//__. В массиве X(1),​X(2),​… ,X(N) каждый элемент равен 0, 1 или 2. Переставьте элементы массива так, чтобы сначала располагались все нули, затем все единицы,​ и, наконец,​ все двойки. Дополнительного массива не вводить! +
-\\ {{.examples:​03-05.bas|}} \\ [[+tab|wmsxbpge>​03-05.bas]] +
-<​code>​ +
-10 DEFINT N,I,J:INPUT N:DIM X(N):​Z=RND(-TIME) +
-30 FOR I=1 TO N:​X(I)=INT(3*RND(1)):?​X(I);:​NEXTI +
-40 FOR I=1 TO N-1:FOR J=I+1 TO N +
-50 IF X(I)<​X(J) THEN GOTO 60 ELSE SWAP X(I),X(J) +
-60 NEXT:​NEXT:?​ +
-70 FOR I=1 TO N:PRINT X(I);:​NEXT +
-run +
-? 10 +
-·0··1··0··0··0··0··2··0··2··2 +
-·0··0··0··0··0··0··1··2··2··2 +
-Ok +
-</​code>​ +
-Программные строки 10–30 позволяют описать и идентифицировать массив X. Операторы в программных строках 40–60 упорядочивают элементы по возрастанию (если предыдущий элемент больше последующего,​то они меняются местами). Операторы 70–й строки выводят на экран дисплея упорядоченный массив X. +
- +
-{{anchor:​e03-06}} __//​Пример 6//__. Дан одномерный массив X(1),​X(2),​…,​X(N). Все его элементы не равные нулю, переписать в начало массива,​ сохраняя порядок,​ а нулевые элементы записать в конец массива. Новый массив +
-не заводить! +
-\\ {{.examples:​03-06.bas|}} \\ [[+tab|wmsxbpge>​03-06.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINTN,​I,​J:​INPUT"​Введите N";​N:​DIM X(N):​C=RND(-TIME) +
-20 FOR I=1 TO N:​X(I)=INT(3*RND(1)) +
-30 PRINT X(I);:NEXT I:​PRINT'​Сформирован массив псевдослучайных чисел для облегчения процесса тестирования программы! +
-50 FOR J=1 TO N-1:FOR I=1 TO N-1 +
-60 IF X(I)=0 THEN SWAP X(I),​X(I+1) +
-70 NEXT I,J +
-80 FOR I=1 TO N:PRINT X(I);:​NEXT +
-run +
-Введите N? 8 +
-·0··0··2··2··0··1··2··0 +
-·2··2··1··2··0··0··0··0 +
-Ok +
-</​code>​ +
-Идея алгоритма проста! Надо менять местами элемент,​ равный нулю, и следующий за ним элемент. Подумайте,​ с какой целью в программе используется цикл с параметром цикла J? +
- +
-{{anchor:​e03-07}} __//​Пример 7//__. Найти наибольший общий делитель(НОД) одномерного массива натуральных чисел A(N). +
-\\ {{.examples:​03-07.bas|}} \\ [[+tab|wmsxbpge>​03-07.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 '​Идентификация массива A(N) +
-10 DEFINTN,​A,​I:​INPUT"​Введите N";​N:​DIMA(N) +
-15 PRINT "​Для каких чисел ищется НОД?"​ +
-20 FOR I=1 TO N:INPUT A(I):NEXT +
-30 FOR I=1 TO N-1 +
-35 '​Далее находится НОД элементов A(I) и А(I+1) с использованием алгоритма Евклида. +
-40 IF A(I)>​A(I+1) THEN A(I)=A(I)-A(I+1) +
-50 IF A(I)<​A(I+1) THEN A(I+1)=A(I+1)-A(I) +
-60 IF A(I)<>​A(I+1) THEN GOTO 40 +
-70 NEXT +
-75 '​Последний вычисленный НОД выводится на экран. +
-80 PRINT A(I) +
-run +
-Введите N? 4 +
-Для каких чисел ищется НОД? +
-? 125 +
-? 25 +
-? 625 +
-? 1225 +
- 25 +
-Ok +
- +
-run +
-Введите N? 4 +
-Для каких чисел ищется НОД? +
-? 12 +
-? 144 +
-? 16 +
-? 20 +
- 4 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-08}} __//​Пример 8//__. Даны 5 цифр: 0, 1, 2, 3, 4. Найти сумму всех трёхзначных чисел, кратных 3, которые можно записать с помощью этих цифр (цифры могут повторяться). +
-\\ {{.examples:​03-08.bas|}} \\ [[+tab|wmsxbpge>​03-08.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT I-K,S:FOR I=1 TO 4:FOR J=0 TO 4:FOR K=0 TO 4 +
-20 IF (I+J+K)MOD3=0 THEN S=S+I*100+J*10+K +
-30 NEXT K,​J,​I:​PRINT"​Искомая сумма=";​S +
-run +
-Искомая сумма= 8937 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-09}} __//​Пример 9//__. Найти количество тех трёхзначных чисел, которые равны сумме факториалов своих цифр (понятием //​подпрограммы//​ не пользоваться!). +
-\\ {{.examples:​03-09.bas|}} \\ [[+tab|wmsxbpge>​03-09.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT I,J:FOR I=100 TO 999 +
-15 '​Ищем факториал старшей цифры! +
-20 P=1:FOR J=1 TO I\100:​P=P*J:​NEXT J +
-25 '​Ищем факториал второй цифры! +
-30 Y=1:FOR J=1 TO (IMOD100)\10:​Y=Y*J:​NEXT J +
-40 Z=1:​A=(IMOD100)MOD10 +
-45 '​Ищем факториал третьей цифры! +
-50 FOR J=1 TO A:​Z=Z*J:​NEXT J +
-60 IF P+Y+Z=I THEN K=K+1:PRINT "​Искомые числа:";​I +
-70 NEXT I:​PRINT"​Количество таких чисел:";​K +
-run +
-Искомые числа: 145 +
-Количество таких чисел: 1 +
-Ok +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Верочка же, получив письмо (она его ждала раньше,​ ещё в марте),​ не сразу, а как–то помедлив,​ словно боясь чего–то,​ встала и, взяв со стола старинный костяной нож с инкрустацией (один перламутровый цветок давно выпал, чернело лишь гнездо на месте, куда он был вставлен),​ и вскрыла конверт неловкой рукой. +
-<WRAP rightalign>​ +
-—//​И.Н.Горелов//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​e03-10}} __//​Пример 10//__. Найти наименьшее трёхзначное число, кратное N, такое, что его первая цифра 7 и все его цифры различны. Программу уместить в одну программную строку! +
-\\ {{.examples:​03-10.bas|}} \\ [[+tab|wmsxbpge>​03-10.bas]] +
-<​code>​ +
-NEW +
-Ok +
-1 '​Пример "​абсолютно нечитабельной"​ программы! +
-5 DEFINTN,​I:​INPUTN:​Y$="​Нет":​FORI=700TO799:​IFI\100<>​(IMOD100)\10THENIFI\100<>​IMOD100MOD10THENIF(IMOD100)\10<>​IMOD100MOD10THENIFIMODN=0THENY$="​Есть!":​CLS:​PRINTY$,​I:​ENDELSEIFI=798THENCLS:​PRINTY$:​ENDELSENEXTELSENEXTELSENEXTELSENEXT +
-run +
-? 5 +
-Есть! 705 +
-Ok +
- +
-run +
-? 70 +
-Нет! +
-Ok +
- +
-run +
-? 18 +
-Есть! 702 +
-Ok +
- +
-run +
-? 56 +
-Есть! 728 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-11}} __//​Пример 11//__. Задан одномерный массив A, элементы которого обозначим A(1), A(2),…, А(N). Найдите длину самой длинной подпоследовательности подряд идущих элементов массива,​ равных 0. +
-\\ {{.examples:​03-11.bas|}} \\ [[+tab|wmsxbpge>​03-11.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT N,​I,​M,​K:​INPUT N:DIM A(N):​X=RND(-TIME) +
-20 FOR I=1 TO N:​A(I)=INT(2*RND(1)):​PRINT A(I);:​NEXT +
-40 FOR I=1 TO N +
-50 IF A(I)=0 THEN K=K+1:IF K>M THEN M=K:NEXT I ELSE NEXT I ELSE K=0:NEXT I +
-60 PRINT:​PRINT"​Максимальная длина:";​M +
-run +
-? 8 +
-·0··1··0··0··1··1··1··1 +
-Максимальная длина:​·2 +
-Ok +
-</​code>​ +
-Программные строки 10–20 позволяют описать массив X и идентифицировать его псевдослучайными целыми числами (для контроля его элементы выводятся на экран в строке 20). Операторы в программных строках 40–60 подсчитывают максимальное количество подряд идущих нулей в массиве и выводят результат на экран. +
- +
-{{anchor:​e03-12}} __//​Пример 12//__. Найдите наибольшую по длине неубывающую подпоследовательность подряд идущих элементов в данной последовательности чисел (в одномерном массиве A(N)). +
-\\ {{.examples:​03-12.bas|}} \\ [[+tab|wmsxbpge>​03-12.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 '​Идентификация массива A(N) псевдослучайными целыми числами (программные строки 10-20). +
-10 DEFINT N,​I,​J,​K,​M:​INPUT N:K=1:DIM A(N):​X=RND(-TIME) +
-20 FOR I=1 TO N:​A(I)=INT(12*RND(1)):​PRINT A(I);:​NEXT +
-30 '​Выделение неубывающей подпоследовательности,​ сравнение ее длины с длиной предыдущей выделенной подпоследовательности;​ наибольшая длина запоминается в переменную M (строки 40-70). +
-40 FOR I=1 TO N-1 +
-50 IF A(I)<​=A(I+1) THEN K=K+1:IF K>M THEN M=K:​J=I+1:​NEXT I ELSE NEXT I ELSE K=1:NEXT I +
-60 ?:?"​Наибольшая длина:";​M:​PRINT"​Подпоследовательность:";​ +
-70 FOR I=J-M+1 TO J:PRINT A(I);:​NEXT +
-Ok +
-run +
-? 8 +
-·0··9··2··10··1··6··3··5 +
-Наибольшая длина·2 +
-Подпоследовательность:​·0··9 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-13}} +
-__//​Пример 13//__. Определите,​ сколько различных элементов встречается в одномерном массиве A(N) более, чем по одному разу. +
-\\ {{.examples:​03-13.bas|}} \\ [[+tab|wmsxbpge>​03-13.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 INPUT"​Введите N";​N:​DIM A(N):​X=RND(-TIME) +
-8 ? "​Исходный массив:"​ +
-10 FOR I=1TO N:​A(I)=INT(10*RND(1)):​PRINT A(I);:​NEXT +
-20 FOR I=1 TO N-1:FOR J=I+1 TO N +
-23 IF A(I)=<​A(J) THEN GOTO 27 ELSE SWAP A(I),A(J) +
-27 NEXT:NEXT :PRINT +
-30 FOR I=1 TO N-1 +
-40 IF A(I)<>​A(I+1) THEN P=0:NEXT I ELSE IF P=0 THEN K=K+1:​P=1:​NEXT ELSE NEXT '​P-флажок! +
-50 PRINT:PRINT K;"​элементов в массиве встречаются более одного раза"​ +
-run +
-Введите N? 13 +
-Исходный массив:​ +
- ​0 ​ 4  7  6  7  5  6  1  2  0  5  2  3 +
- 5 элементов в массиве встречаются более одного раза +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-14}} __//​Пример 14//__. Определить количество повторяющихся элементов в одномерном массиве A(N). +
-\\ {{.examples:​03-14.bas|}} \\ [[+tab|wmsxbpge>​03-14.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5  INPUT N:DIM A(N) +
-6  X=RND(-TIME) +
-7  FOR I=1 TO N:​A(I)=INT(10*RND(1)):​PRINT A(I);:​NEXT:​PRINT +
-10    S=0 +
-20    FOR I=1 TO N +
-30       P=0 +
-40       FOR J=1 TO N +
-50          IF A(I)=A(J) THEN P=P+1 +
-60       NEXT J +
-70 IF P>1 THEN S=S+1 +
-80 NEXT I:PRINT S +
-run +
-? 10 +
- ​3 ​ 7  5  6  9  6  9  4  5  0 +
- 6 +
-Ok +
- +
-run +
-? 7 +
- ​9 ​ 2  7  3  0  0  1 +
- 2 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-15}}__//​Пример 15//__. Из заданного на плоскости множества точек выбрать три такие, не лежащие на одной прямой,​ которые будут вершинами треугольника:​ +
-  * наибольшей площади;​ +
-  * наименьшего периметра. +
-\\ {{.examples:​03-15.bas|}} \\ [[+tab|wmsxbpge>​03-15.bas]] +
-<​code>​ +
-NEW +
-Ok +
-20 DEFINT H,​I-K,​M:​INPUT"​Число точек";​H:​D=RND(-TIME):​M=2*H +
-30 DIM A(M),​B(M),​C(M):​IF H<3 THEN RUN 20 +
-40 FOR I=1 TO M:​A(I)=INT(190*RND(1)):​B(I)=A(I):​C(I)=A(I):​NEXT:​S=0:​P=900 '​Генерируем три одинаковых массива координат точек плоскости случайным образом. +
-50 FOR I=2 TO M STEP 2 +
-60 FOR J=2 TO M STEP 2 +
-70 FOR K=2 TO M STEP 2 +
-80 U=SQR((A(I)-B(J))^2+(A(I-1)-B(J-1))^2):​Q=SQR((A(I)-C(K))^2+(A(I-1)-C(K-1))^2):​W=SQR((B(J)-C(K))^2+(B(J-1)-C(K-1))^2):​G=U+Q+W '​Нашли периметр треугольника. +
-90 V=SQR((G/​2)*(G/​2-U)*(G/​2-Q)*(G/​2-W)) '​Нашли его площадь. +
-100 IF V<1.E-10 THEN 130'​Этим оператором гарантируем,​ что взяты три различные точки, не лежащие на одной прямой. +
-110 IF G<P THEN P=G:​A1=A(I):​A2=A(I-1):​B1=B(J):​B2=B(J-1):​C1=C(K):​C2=C(K-1)'​Ищем треугольник с наименьшим периметром и запоминаем координаты его вершин. +
-120 IF V>S THEN S=V:​A3=A(I):​A4=A(I-1):​B3=B(J):​B4=B(J-1):​C3=C(K):​C4=C(K-1)'​Ищем треугольник наибольшей площади и запоминаем координаты его вершин +
-130 NEXT K,J,I +
-140 PRINT"​Вершины треугольника наиб.площади:​(";​A3;",";​A4;"​),​(";​B3;",";​B4;"​),​(";​C3;",";​C4;"​);"​ +
-150 PRINT"​Площадь треугольника:";​S +
-160 PRINT"​Вершины треугольника наим.периметра:​(";​A1;",";​A2;"​),​(";​B1;",";​B2;"​),​(";​C1;",";​C2;"​);"​ +
-170 PRINT"​Периметр треугольника:";​P +
-180 FOR I=1 TO 5000:NEXT '​Задержка по времени (≈13 сек)! +
-185 '​Графическая иллюстрация полученного результата. +
-190 SCREEN 2 +
-200 FOR I=2 TO M STEP 2:​PSET(A(I),​A(I-1)),​2:​NEXT +
-210 LINE(A1,​A2)-(B1,​B2),​1:​LINE-(C1,​C2),​1:​LINE-(A1,​A2),​1 +
-220 LINE(A3,​A4)-(B3,​B4),​2:​LINE-(C3,​C4),​2:​LINE-(A3,​A4),​2 +
-230 GOTO 230'​На экране изображены искомые треугольники! +
-run +
-Число точек? 5 +
-Вершины треугольника наиб.площади:​( 87 , 175 ),( 160 , 85),( 165 , 7 ); +
-Площадь треугольника:​ 2622.0000000032 +
-Вершины треугольника наим.периметра:​( 142 , 57 ),( 165 , 7 ),( 161 , 24 ); +
-Периметр треугольника:​ 110.57946634916 +
-Далее следует графическая иллюстрация полученного решения. +
-</​code>​ +
- +
-{{anchor:​e03-16}} __//​Пример 16//__. Конечное множество из N точек в трёхмерном пространстве задано своими координатами:​ (X(N),​Y(N),​Z(N)),​ N=1,​2,​…,​n. Составьте программу подсчёта количества тех точек данного +
-множества,​ которые принадлежат:​ +
-  * шару ​ X²+y²+z²≤25;​ +
-  * полупространству x+y+z≤3;​ +
-  * пересечению шара и полупространства;​ +
-  * объединению шара и полупространства. +
-{{.examples:​03-16.bas|}} \\ [[+tab|wmsxbpge>​03-16.bas]] +
-<​code>​ +
-NEW +
-Ok5 '​Идентификация массивов X,Y,Z псевдослучайными целыми числами (программные строки 10–30). +
-10 DEFINT N,I:INPUT "​Количество точек";​N +
-20 DIM X(N),​Y(N),​Z(N):​U=RND(-TIME) +
-25 PRINT " X  Y  Z " +
-30 FOR I=1 TO N:​X(I)=INT(11*RND(1)-5):​Y(I)=INT(11*RND(1)-5):​Z(I)=INT(11*RND(1)-5):​PRINTX(I)Y(I)Z(I):​NEXT +
-35 '​Подсчет количества точек,​лежащих в шаре (строки 40-60). +
-40 FOR I=1 TO N +
-50 IF(X(I)^2)+(Y(I)^2)+(Z(I)^2)<​=25THENK=K+1:​NEXTELSE NEXT +
-60 PRINT "​Количество точек,​лежащих в шаре:";​K +
-65 '​Подсчет количества точек, принадлежащих полупространству (строки 70-90). +
-70 FOR I=1 TO N +
-80 IF X(I)+Y(I)+Z(I)<​=3 THEN C=C+1:NEXTI ELSE NEXTI +
-90 PRINT "​Количество точек,​принадлежащих полупространству:";​C +
-95 '​Подсчет количества точек,​лежащих в шаре и одновременно в полупространстве (строки 100-120). +
-100 FOR I=1 TO N +
-110 IF X(I)+Y(I)+Z(I)=<​3 AND (X(I))^2+(Y(I))^2+(Z(I))^2<​=25 THEN B=B+1NEXT ELSE NEXT +
-120 PRINT "​Количество точек,​принадлежащих пересечению шара и полупространства:";​B +
-125 '​Подсчет количества точек,​принадлежащих объединению шара и полупространства (строки 130-140) +
-130 P=C-B+K +
-140 PRINT "​Количество точек,​принадлежащих объединению шара и полупространства:";​P +
-run +
-Количество точек? 5 +
- +
- ​X ​ Y  Z +
- 0 -3  3 +
--4 -4  4 +
- ​4 ​ 5  4 +
--5  5  1 +
--1  4  4 +
- +
-Количество точек,​лежащих в шаре: 1 +
-Количество точек,​принадлежащих полупространству:​ 3 +
-Количество точек,​принадлежащих пересечению шара и полупространства:​ 1 +
-Количество точек,​принадлежащих объединению шара и полупространства:​ 3 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-17}} __//​Пример 17//__. В заданном двухмерном массиве A(N,M) найти минимальное из чисел, встречающееся там более одного раза. +
-\\ {{.examples:​03-17.bas|}} \\ [[+tab|wmsxbpge>​03-17.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 '​Описание массива A(N,M) и заполнение его псевдослучайными целыми числами (строки 10-20). +
-10 DEFINT I,​J,​N,​M,​Y,​K,​L:​INPUT N,M:DIM A(N,​M):​X=RND(-TIME) +
-20 FOR I=1 TO N:FOR J=1 TO M:​A(I,​J)=INT(10*RND(1)):​PRINT A(I,​J);:​NEXT J:​PRINT:​NEXTI:​IF N+M=2 THEN RUN10 +
-30 '​Идентификация дополнительного массива B (строки 40-50). +
-40 K=N*M:DIM B(K) +
-50 FORI=1TO N:FOR J=1 TO M:​Y=M*(I-1)+J:​B(Y)=A(I,​J):​NEXTJ,​I +
-60 '​Этот блок (строки 70-110) позволяет найти минимальное число элементов,​ встречающихся в массиве более одного раза. +
-70 FOR Y=1 TO K-1:FOR L=Y+1 TO K +
-80 IF B(Y)<​B(L) THEN 90 ELSE SWAP B(Y),B(L) +
-90 NEXT:NEXT +
-100 FOR I=1 TO K-1 +
-110 IF B(I)=B(I+1) THEN PRINT"​Минимальное число:";​B(I) ELSE NEXTI:​PRINT"​Такого элемента нет!"​ +
-run +
-? 3,4 +
-·3··0··3··9 +
-·9··0··3··2 +
-·9··3··9··3 +
-Минимальное число: 0 +
-Ok +
- +
-run +
-? 1,2 +
-·7··1 +
-Такого элемента нет! +
-Ок +
-</​code>​ +
- +
-{{anchor:​e03-18}} __//​Пример 18//__. Определите,​ сколько различных элементов в данном двухмерном массиве А(N,M)? +
-\\ {{.examples:​03-18.bas|}} \\ [[+tab|wmsxbpge>​03-18.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 '​Идентификация массива A(N,M) псевдослучайными целыми числами и вывод его на экран дисплея для контроля (строки 10-20). +
-10 DEFINT N,​M,​I,​J,​Y,​K,​L:​INPUT N,M:DIM A(N,​M):​X=RND(-TIME) +
-20 FOR I=1 TO N:FOR J=1 TO M:​A(I,​J)=INT(10*RND(1)):?​A(I,​J);:​NEXT J:?:​NEXTI:​IF N+M=2 THEN ?"​Один-одинешенек!":​END +
-30 '​Идентификация дополнительного массива B (строки 40-50). +
-40 K=N*M:DIM B(K) +
-50 FOR I=1 TON:FOR J=1 TOM:​Y=M*(I-1)+J:​B(Y)=A(I,​J):​NEXTJ,​I +
-65'​Упорядочивание элементов в массиве B(строки 70-90) +
-70 FOR Y=1 TO K-1:FOR L=Y+1 TO K +
-80 IF B(Y)<​B(L) THEN 90 ELSE SWAP B(Y),B(L) +
-90 NEXT:NEXT +
-93 '​Подсчет количества различных элементов в массиве B и вывод результата на экран дисплея (строки 95-120). +
-95 U=1 +
-100 FOR I=1 TO K-1 +
-110 IF B(I)<>​B(I+1) THEN U=U+1:NEXT I ELSE NEXT I +
-120 PRINT"​Количество разл.элементов:";​U +
-run +
-? 3,3 +
-·9··6··9 +
-·3··9··4 +
-·2··1··8 +
-Количество разл.элементов:​·7 +
-Ok +
- +
-run +
-? 3,4 +
-·1··5··3··5 +
-·8··9··7··5 +
-·0··4··4··9 +
-Количество разл.элементов:​·8 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-19}} __//​Пример 19//__. Проверьте,​ есть ли в двухмерном массиве C(M,N) отрицательные элементы,​ если есть, найдите среди них тот, у которого сумма индексов будет наименьшей. +
-\\ {{.examples:​03-19.bas|}} \\ [[+tab|wmsxbpge>​03-19.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 '​Идентификация массива A(M,N) (строки 10-30). +
-10 DEFINT M,​N,​I,​J,​K:​INPUT M,N:DIM A(M,​N):​K=N+M:​X=RND(-TIME) +
-20 FOR I=1 TO M:FOR J=1 TO N +
-30 A(I,​J)=INT(11*RND(1)-5):​PRINT A(I,​J);:​NEXTJ:?:​NEXT I +
-45 IF M=1 AND N=1 THEN IF A(1,1)<0 THEN ?"​Искомый элемент:";​A(1,​1):​END ELSE ?"​Такого элемента нет!":​END'​Случай M=N=1 +
-47 '​Нахождение отрицательного элемента массива A, у которого сумма индексов минимальна (строки 50-70). +
-50 FOR I=1 TO M:FOR J=1 TO N +
-60 IF A(I,J)<0 THEN IF I+J<K THEN K=I+J:​C=A(I,​J):​NEXTJ:​NEXTI ELSE NEXT J:NEXT I ELSE NEXT J:NEXT I +
-70 PRINT"​Искомый отрицат.элемент:";​C +
-run +
-? 2,5 +
-·0··2··3·-3··3 +
--5··5·-4··3·-5 +
-Искомый отрицат.элемент:​-5 +
-Ok +
- +
-run +
-? 2,3 +
--2··1··5 +
-·1··3··4 +
-Искомый отрицат.элемент:​-2 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-20}} __//​Пример 20//__. Операция сглаживания матрицы даёт новую матрицу того же размера,​ каждый элемент которой получается как среднее арифметическое имеющихся соседей соответствующего элемента исходной +
-матрицы. Построить результат сглаживания заданной вещественной матрицы A размером N×N. +
-\\ {{.examples:​03-20.bas|}} \\ [[+tab|wmsxbpge>​03-20.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT"​FORMAT";​A$ +
-15 '​FORMAT-строковое выражение,​ состоящее из символов "#"​ и десятичной точки (например,​ ##.###); используется в операторе ''​PRINTUSING''​ (строка 210) для вывода элементов массива с требуемой точностью. +
-16 '​Точность определяется количеством символов "#",​ стоящих правее десятичной точки. +
-20 DEFINT N,​I,​J:​INPUT"​Число строк (столбцов)";​N +
-30 DIM A(N,​N),​B(N,​N):​K=RND(-TIME) +
-35 '​Формирование матрицы ​ A, элементами которой являются случайные числа (для облегчения тестирования программы!). +
-40 FOR I=1 TO N:FOR J=1 TO N +
-50 A(I,​J)=INT(10*RND(1)):​PRINT A(I,J); +
-60 NEXT J:​PRINT:​NEXT I:​PRINT"​Результат сглаживания"​ +
-70 IF N=2 THEN 160 ELSE IF N=1 THEN ?"​Спорный вопрос!":​END +
-75 '​Программные строки 80-190 позволяют сгладить матрицу A(N,​N).Результат сглаживания - матрица B(N,N). +
-80 FOR I=2 TO N-1:FOR J=2 TO N-1 +
-90 B(I,​J)=(A(I-1,​J)+A(I,​J-1)+A(I,​J+1)+A(I+1,​J))/​4:​NEXT J,I +
-100 FOR J=2 TO N-1 +
-110 B(1,​J)=(A(1,​J-1)+A(2,​J)+A(1,​J+1))/​3 +
-120 B(N,​J)=(A(N,​J-1)+A(N-1,​J)+A(N,​J+1))/​3:​NEXT J +
-130 FOR I=2 TO N-1 +
-140 B(I,​1)=(A(I-1,​1)+A(I,​2)+A(I+1,​1))/​3 +
-150 B(I,​N)=(A(I-1,​N)+A(I,​N-1)+A(I+1,​N))/​3:​NEXT I +
-160 B(1,​1)=(A(1,​2)+A(2,​1))/​2:​B(1,​N)=(A(1,​N-1)+A(2,​N))/​2 +
-180 B(N,​1)=(A(N-1,​1)+A(N,​2))/​2:​B(N,​N)=(A(N-1,​N)+A(N,​N-1))/​2 +
-200 FOR I=1 TO N:FOR J=1 TO N +
-210 PRINT USING A$;​B(I,​J);:​NEXT J:?:NEXT I +
-run +
-FORMAT? ###.## +
-Число строк (столбцов)?​ 3 +
-·2··0··7 +
-·9··9··9 +
-·1··7··1 +
-Результат сглаживания +
-··4.50··6.00··4.50 +
-··4.00··6.25··5.67 +
-··8.00··3.67··8.00 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-21}} __//​Пример 21//__. Для заданной целочисленной матрицы найдите максимум среди сумм элементов диагоналей,​ параллельных главной диагонали матрицы размером M×M.  +
-\\ {{.examples:​03-21.bas|}} \\ [[+tab|wmsxbpge>​03-21.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 '​Идентификация массива A(M,M) (строки 10-30). +
-10 DEFINT M,​I,​J,​K:​INPUT M:IF M<=1 THEN 10 +
-20 DIM A(M,​M):​X=RND(-TIME) +
-30 FOR I=1 TO M:FOR J=1 TO M:​A(I,​J)=INT(10*RND(1)):​PRINT A(I,​J);:​NEXTJ:​PRINT:​NEXT I +
-35 '​Нахождение максимальной среди сумм элементов диагоналей,​ расположенных выше главной (строки 40-50). +
-40 FOR K=1 TO M-1:FOR I=1 TO M:FOR J=1 TO M +
-50 IF J=I+K THEN B=B+A(I,​J):​NEXT J:NEXT I ELSE NEXTJ:​NEXTI:​IF B>C THEN C=B:​B=0:​NEXT K ELSE B=0:NEXT K +
-55 '​Нахождение максимальной среди сумм элементов диагоналей,​ расположенных ниже главной (строки 60-70). +
-60 FOR K=1 TO M-1:FOR I=1 TO M:FOR J=1 TO M +
-70 IF J=I-K THEN B=B+A(I,​J):​NEXT J:NEXTI ELSE NEXTJ:​NEXTI:​IF B>D THEN D=B:​B=0:​NEXT K ELSE B=0:NEXT K +
-80 IF C>D THEN PRINT C ELSE PRINT D '​Сравнение этих максимумов и вывод большего на экран дисплея. +
-run +
-? 4 +
-·5··8··4··8 +
-·0··3··2··7 +
-·6··6··7··3 +
-·7··6··6··9 +
-·13 +
-Ok +
- +
-run +
-? 3 +
-·3··6··6 +
-·8··0··2 +
-·3··6··2 +
-·14 +
-Ok +
- +
-run +
-? 5 +
-·2··0··5··7··7 +
-·9··6··7··2··9 +
-·9··9··8··5··5 +
-·6··9··1··1··7 +
-·7··3··9··8··3 +
-·27 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-22}} __//​Пример 22//__. Вычислить сумму тех элементов двухмерного целочисленного массива A(M,N), в десятичной записи которых используются только цифры 0, 1, 2, 3. +
-\\ {{.examples:​03-22.bas|}} \\ [[+tab|wmsxbpge>​03-22.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT M,​N,​I,​J,​K,​A:​INPUT"​Введите M и N";​M,​N +
-Кто геометрическое среднее между атомом и Солнцем?​ \\ +
-20 INPUT"​Числовой отрезок[X,​Y]";​X,​Y +
-30 Z=RND(-TIME):​DIM B(M,​N),​A(M,​N) +
-40 '​Заполнение массива B(M,N) псевдослучайными целыми числами из отрезка[X,​Y](строки 50-70) +
-50 FOR I=1 TO M:FOR J=1 TO N:​B(I,​J)=INT((Y-X+1)*RND(1)+X):​A(I,​J)=B(I,​J):​NEXT J,I +
-80 S=0:FOR I=1 TO M:FOR J=1 TO N +
-90 '​Пока не просмотрим все цифры числа A(i,​j),​выполняем цикл "​пока"​(строки 100-160) +
-100 IF A(I,J)=0 THEN 180 ELSE FOR K=1 TO 0 STEP 1 +
-120 B=ABS(A(I,​J))-INT(ABS(A(I,​J))/​10)*10 '​Выделяем последнюю цифру числа A(i,j) +
-130 IF B>=4 THEN 180 ELSE A(I,​J)=(ABS(A(I,​J))-B)/​10 +
-150 K=A(I,J) '​проверка условия:​ если A(i,​j)=0,​то из цикла "​пока"​ выходим +
-160 NEXT K +
-170 IF A(I,​J)=0THEN S=S+B(I,​J)'​Ищем сумму нужных элементов +
-180 NEXT J,I:FOR I=1 TO M:FOR J=1 TO N +
-210 PRINT B(I,​J);:​NEXT J:​PRINT:​NEXT I:?"​Искомая сумма:";​S +
-run +
-Введите M и N? 4,6 +
-Числовой отрезок[X,​Y]?​ 1,9 +
-9  4  9  3  5  6 +
-3  1  6  4  3  3 +
-1  9  2  3  9  1 +
-3  8  4  8  9  2 +
-Искомая сумма: 25 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e03-23}} __//​Пример 23//__. Подсчитайте количество элементов двухмерного массива A(M,N) натуральных чисел, которые являются составными. +
-\\ {{.examples:​03-23.bas|}} \\ [[+tab|wmsxbpge>​03-23.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT M,​N,​I,​J,​A,​K:​INPUT"​Введите M и N";​M,​N:​X=RND(-TIME):​DIM A(M,N):IF M<1 OR N<1 THEN RUN 10 +
-30 FOR I=1 TO M:FOR J=1 TO N +
-40 A(I,​J)=INT(30*RND(1)+1):​IF A(I,J)=2 THEN PRINTUSING"​\ ​ \";​STR$(A(I,​J))+"​*";:​NEXT:​PRINT:​NEXT +
-50 K=0:FOR K=2 TO A(I,J)-1 +
-60 IF A(I,​J)/​K<>​FIX(A(I,​J)/​K) THEN NEXT K:​PRINTUSING"​\ ​ \";​STR$(A(I,​J))+"​*";:​NEXT J:​PRINT:​NEXT I ELSE Y=Y+1:PRINT USING"​\ ​ \";​STR$(A(I,​J))+"​ ";:​NEXT J:​PRINT:​NEXT I +
-70 PRINT"​Звездочками отмечены простые числа;​составных чисел в Вашем массиве";​Y +
-run +
-Введите M и N? 3,5 +
-·27··20··25··0···2* +
-·26··17*·23*·2*··23* +
-·20··12··22··9···21 +
-Звездочками отмечены простые числа;​составных чисел в Вашем массиве·10 +
-Ok +
-</​code>​ +
-В этой программе во время идентификации массива A(M,N) случайными числами сразу же производится проверка каждого элемента массива:​ является ли он простым?​ Если "​да",​то на экран этот элемент выводится со "​звёздочкой"​ ("​∗"​) позади. Если "​нет",​ то — без неё. Затем подсчитывается количество составных чисел и результат выводится на экран. +
- +
-{{anchor:​e03-24}} __//​Пример 24//__. //​Характеристикой//​ столбца целочисленной матрицы назовём сумму модулей её отрицательных чётных элементов. Переставляя столбцы заданной матрицы,​ расположить их в соответствии с ростом характеристик. +
-\\ {{.examples:​03-24.bas|}} \\ [[+tab|wmsxbpge>​03-24.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT M,​N,​I,​J,​W,​K,​B,​D:​INPUT"​Укажите M,​N";​M,​N +
-15 IF M<2 OR N<2 THEN PRINT "​Слишком малое количество столбцов (строк)!":​RUN 10 +
-20 INPUT"​Числовой отрезок[X,​Y]";​X,​Y +
-30 Z=RND(-TIME):​DIM A[M,​N],​Q[M,​N],​L[N],​F[N] +
-40 '​Заполняем массив A[M,N] случайными целыми числами из отрезка [X,Y] и копируем его в массив Q[M,​N](строки 50-70) +
-50 FOR I=1 TO M:FOR J=1 TO N +
-60 A[I,​J]=INT((Y-X+1)*RND(1)+X):​Q[I,​J]=A[I,​J] +
-70 NEXT J,I +
-80 '​Находим характеристики столбцов(строки 90-110) +
-90 FOR J=1 TO N:FOR I=1 TO M +
-100 IF A[I,J]<0 AND ABS(A[I,​J])MOD2=0 THEN L[J]=L[J]+ABS(A[I,​J]) +
-110 F[J]=L[J]:​NEXT I,J +
-120 '​Упорядочиваем столбцы по возрастанию характеристик(строки 130-180) +
-130 FOR W=1 TO N-1 '​Удивительный цикл! +
-140 FOR B=1 TO N-1:FOR K=B+1 TO N +
-150 IF L[B]<​=L[K] THEN 180 ELSE SWAP L[B],L[K] +
-170 FOR D=1 TO M:SWAP A[D,​B],​A[D,​K]:​NEXT D +
-180 NEXT K,B,W +
-190 '​Вывод результатов +
-200 FOR I=1 TO M +
-210 FOR J=1 TO N:PRINT USING"####";​Q[I,​J];:​NEXTJ:?​ SPC(4) +
-220 FOR J=1 TO N:PRINT USING"####";​A[I,​J];:​NEXT J:PRINT +
-230 NEXT I +
-240 FOR H=0 TO 30:PRINT "​-";:​NEXT H:PRINT +
-250 'А теперь заполняем строки характеристик! +
-260 FOR J=1 TO N:PRINT USING"####";​F[J];:​NEXT:?​ SPC(4) +
-270 FOR J=1 TO N:PRINT USING"####";​L[J];:​NEXT +
-run +
-Укажите M,N? 4,3 +
-Числовой отрезок[X,​Y]?​ -40,10 +
- -17 -18  -6      -6 -17 -18 +
- -23 -16   ​1 ​      1 -23 -16 +
-   1 -38   ​7 ​      ​7 ​  1 -38 +
- ​-12 ​ -5  -1      -1 -12  -5 +
------------------------------- +
-  12  72   ​6 ​      ​6 ​ 12  72    ◀──── строки характеристик +
-Ok +
-</​code>​ +
-Подумайте,​ каким был бы результат тестового примера,​ если бы в программе отсутствовал цикл с параметром W (строки 130–180). +
- +
-{{anchor:​e03-25}} __//​Пример 25//__. Вычисление определённого интеграла от функции,​ заданной на отрезке [-1,1], по квадратурной формуле Гаусса. +
-\\ {{.examples:​03-25.bas|}} \\ [[+tab|wmsxbpge>​03-25.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT N,I:DEF FNF(Z)=Z*SIN(Z) +
-20 INPUT"​Порядок интегрирования=";​N:​DIM X[N],H[N] +
-40 IF N=2 THEN RESTORE 160 +
-50 IF N=3 THEN RESTORE 170 +
-60 IF N=4 THEN RESTORE 180 +
-70 IF N=5 THEN RESTORE 190 +
-80 FOR I=1 TO N:READ X[I]:NEXT +
-90 IF N=2 THEN RESTORE 200 +
-100 IF N=3 THEN RESTORE 210 +
-110 IF N=4 THEN RESTORE 220 +
-120 IF N=5 THEN RESTORE 230 +
-130 FOR I=1 TO N:READ H[I]:​NEXT:​J=0 +
-140 FOR I=1 TO N:​J=J+FNF(X[I])*H[I] +
-150 NEXT:PRINT "​Интеграл=";​J:​END +
-155 '​Коэффициенты метода Гаусса. +
-160 DATA-.57735026919,​ .57735026919 +
-170 DATA-.774596669241,​0 , .774596669241 +
-180 DATA-.861136311594,​-.339981043585,​.339981043585,​.861136311594 +
-190 DATA-.906179845939,​-.538469310106,​0,​.538469310106,​.906179845939 +
-200 DATA 1,1 +
-210 DATA .55555555555556,​.88888888888889,​.55555555555556 +
-220 DATA .347854845137,​.652145154863,​.652145154863,​.347854845137 +
-230 DATA .236926885056,​.478628670499,​.56888888888889,​.478628670499,​.236926885056 +
-run +
-Порядок интегрирования=?​ 2 +
-Интеграл= .6302420371144 +
-Ok +
- +
-run +
-Порядок интегрирования=?​ 4 +
-Интеграл= .6023395913427 +
-Ok +
-</​code>​ +
- +
-====== Диск с примерами ====== +
- +
-{{.examples:​examples03.dsk|Загрузить образ диска}} +
- +
-[[+tab|wmsxbpged>​examples03.dsk|Открыть диск в WebMSX]] +
- +
- +
----- +
- +
-[<>​] +
- +
- +
-{{tag>​MSX BASIC Book_msxbpg}}+
msx/basic_programming_guide/03.1584820331.txt.gz · Последние изменения: 2020-03-21 22:52 (внешнее изменение)