Кетков Ю.Л., Кетков А.Ю. Практика программирования: Бейсик, Паскаль, Си - файл n10.htm

приобрести
Кетков Ю.Л., Кетков А.Ю. Практика программирования: Бейсик, Паскаль, Си
скачать (482.6 kb.)
Доступные файлы (27):
n2.gif2kb.14.08.2001 16:11скачать
n4.gif2kb.14.08.2001 16:11скачать
2.1.gif6kb.06.07.2002 04:38скачать
2.2.gif5kb.06.07.2002 04:44скачать
n9.gif2kb.14.08.2001 16:11скачать
n10.htm393kb.06.07.2002 04:47скачать
3.1.gif76kb.06.07.2002 04:54скачать
n13.gif2kb.14.08.2001 16:11скачать
n15.gif2kb.14.08.2001 16:11скачать
n17.gif2kb.14.08.2001 16:11скачать
274.1.gif1kb.06.07.2002 05:07скачать
274.2.gif9kb.06.07.2002 05:17скачать
n21.gif2kb.14.08.2001 16:11скачать
n23.gif2kb.14.08.2001 16:11скачать
8.1.gif1kb.06.07.2002 05:20скачать
8.2a.gif2kb.06.07.2002 05:22скачать
8.2b.gif2kb.06.07.2002 05:26скачать
8.2c.gif4kb.06.07.2002 05:27скачать
8.2d.gif5kb.06.07.2002 05:28скачать
8.3a.gif2kb.06.07.2002 05:32скачать
8.3b.gif3kb.06.07.2002 05:33скачать
8.3c.gif4kb.06.07.2002 05:39скачать
n33.gif2kb.14.08.2001 16:11скачать
n35.gif2kb.14.08.2001 16:11скачать
n36.jpg11kb.21.11.2002 05:56скачать
n39.gif2kb.14.08.2001 16:11скачать
n40.txt2kb.27.07.2001 12:20скачать

n10.htm

  1   2   3   4

Глава 2


Работа с числовыми данными


Современные представления о числовых данных базируются на так называемых позиционных системах счисления. Для этих систем характерно основание системы р, степень которого определяет вес цифры а (а = о, 1, 2.....P-I) в зависимости от занимаемой позиции:


ak ak-1 . . . a1a0, b-1b-2 ... b-m = ak*pk + ak-1*pk-1 + . . . + a1*p1 + a0*p0 + b-1p-1 + + b-2*p-2 + . . . + b-m*p-m


Главенствующую роль в человеческом общении играет десятичная система счисления (р = 10; а =0, 1, ..., 9). Однако ЭВМ используют более рациональную двоичную систему (р = 2; а = 0,1). Единственным ее недостатком является большая длина чисел. Количество разрядов (цифр) в двоичном представлении числа примерно в три раза превышает количество десятичных цифр. Для преодоления этого неудобства программисты прибегают к более компактной записи двоичных кодов в виде восьмеричных или шест-надцатеричных чисел. При этом три или четыре смежные двоичные цифры заменяют одной восьмеричной или шестнадцатеричной цифрой. Например:


19210 - 110000002,

110000002 = 3003,

110000002 = C016.


Внешнее и внутреннее представление числовых данных


Под внешним представлением числовой информации подразумеваются способы записи данных, используемые в текстах программ, при наборе чисел, вводимых в ЭВМ по запросу программы, при отображении результатов на экране дисплея или на принтере. Кроме естественного представления числовых констант в виде целого или вещественного числа, языки программирования допускают различные добавки в начале ("префиксы") или конце ("суффиксы") числа, определяющие способы преобразования и хранения данных в памяти компьютера.


Во входном языке системы QBasic такого рода добавки представлены одним из символов %, !, & или #, приписываемым вслед за числом, и одной из двухсимвольных комбинаций &в, &о или &н, располагаемой перед числом:


В Си к аналогичным суффиксам относятся указания об удвоенной длине целых чисел (буквы L или l), указания о вещественном формате числа, не содержащего в своей записи десятичной точки или десятичного порядка (буква F или f), указания об использовании беззнакового представления целых чисел (буква и или и). Префиксы в Си используются для записи восьмеричных (число начинается с о) или шестнадцатеричных (числу предшествует одна из комбинаций Ох или ох) констант:


В Паскале используется единственный префикс — символ $, предшествующий шестнадцатеричному числу:


$ОА, $FOA5, $FF00140D.


Наличие в естественной записи числа точки (3.1415) или указателя десятичного порядка (314.1592б5е-02) означает, что соответствующее значение представлено в ЭВМ в виде вещественного числа с плавающей запятой.


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


Самые короткие числа со знаком представлены в памяти ЭВМ одним байтом, в котором может разместиться любое число из диапазона от —128 до + 127. В Си для описания данных такого типа используется спецификатор char, а в Паскале — shortint.


В одном же байте может быть расположено и самое короткое целое число без знака. В Си для описания таких данных служит спецификатор unsigned char, в Паскале — byte, диапазон допустимых данных при этом смещается вправо и равен [0, 255]. QBasic не располагает языковыми средствами для работы с однобайтовыми целыми числами.


Вторая категория целых чисел представлена двухбайтовыми данными. В варианте со знаком они предлагают диапазон от —32 768 до +32 767, в варианте без знака — от 0 до 65 535.


QBasic обеспечивает работу с двухбайтовыми числами со знаком для переменных, описанных как AS INTEGER или устаревшее DEFINT,. и переменных, чьи имена заканчиваются символом %. Двухбайтовые целые без знака в QBasic записываются в виде двоичных, восьмеричных или шестнадцатерич-ных констант. Однако арифметические операции над такими данными иногда выполняются некорректно.


Си использует для описания двухбайтовых целочисленных данных спецификаторы int и unsigned int. В Паскале для этой же цели служат спецификаторы integer и word. Оба языка корректно выполняют арифметические операции и с беззнаковыми данными при условии, что результат не выходит за пределы разрешенного диапазона.


Третья категория целых чисел в IBM PC представлена четырехбайтовыми данными. В варианте со знаком они перекрывают диапазон от —2 147 483 648 до +2 147 483 647, в варианте без знака — от 0 до 4 294 967 295.


В QBasic допустимы только данные со знаком и имена переменных такого типа описываются как AS LONG или DEFLNG. К ним же относятся и переменные, чьи имена заканчиваются символом &.


Для описания четырехбайтовых данных целого типа в Си используются спецификаторы long (эквивалент long int) и unsigned long. В Паскале работа с длинными целыми без знака не предусмотрена. Там можно оперировать с четырехбайтовыми данными только типа longint.


Следует помнить, что для хранения любых целых чисел со знаком в IBM PC используется дополнительный код, что сказывается на представлении отрицательных чисел:


+5 0 0000101 0 000000000000101


-5 1 1111011 1 111111111111011


Наиболее часто применяемые типы вещественных чисел представлены короткими (4 байта) и длинными (8 байт) данными.


В QBasic им соответствуют описания AS SINGLE (устаревшее — DEFSNG) и AS DOUBLE (устаревшее — DEFDBL). Си использует для этой же цели спецификаторы float И double, Паскаль — single И double.


Короткий вещественный формат по модулю обеспечивает представление чисел в диапазоне от 10-38 до 10+38 примерно с 7—8 значащими цифрами. Для 8-байтового формата диапазон существенно расширяется — от 10-308 до 10+308, а количество значащих цифр увеличивается до 15—16.


Сопроцессор IBM PC предлагает еще два формата данных, занимающих соответственно 8 и 10 байт. Первый из них допускает работу с целыми числами из диапазона от —263 до 263-1. Второй формат перекрывает диапазон данных (по модулю) от 10-4932 до 10+4932, сохраняя 19—20 значащих цифр. Расширенный формат вещественных данных можно использовать в программах на Си (long double) и на Паскале (extended). А формат сверхдлинных целых чисел используется только в Паскале, но там они почему-то отнесены к вещественным данным типа сотр.


В Паскале по традиции сохранился еще один тип вещественных данных -real, занимающий в памяти 6 байт. Его диапазон совпадает с типом single, однако количество значащих цифр несколько больше — 10—12. Формат real не поддерживается аппаратными средствами IBM PC, поэтому операции над такими данными выполняются с помощью подпрограмм, что существенно увеличивает время решения задачи.


В машинном представлении вещественных данных разного типа на IBM PC не выдержана какая-то общая идеология. Объясняется это, по всей вероятности, разными наслоениями на прежние аппаратные решения, которые принимались при разработке процессоров в разных отделениях фирмы Intel. Поэтому здесь имеют место такие нюансы, как сохранение или не сохранение старшего бита мантиссы, представление мантиссы в виде чисто дробного (0,5 < < m < i) или смешанного (1 < m < 2) числа и т. п. Прикладных программистов эти детали мало интересуют, однако при создании специальных системных компонент с точным представлением данных приходится считаться.


Ввод числовой информации


Каких-либо особых проблем с вводом числовой информации в программах не возникает. Но на некоторые детали в том или ином алгоритмическом языке надо обратить внимание.


В QBasic можно натолкнуться на неприятности при вводе нескольких числовых значений в одном операторе. Например:


INPUT А,В,С


Числовые данные, набираемые пользователем, должны быть разделены пробелом. Если в наборе второго или третьего значения вы допустите ошибку, то последует сообщение Redo from start, которое заставит вас повторить
ввод всех трех чисел с самого начала. Некоторые программисты даже предпочитают вводить одним оператором только одно значение. Несоответствие между типом переменной и вводимым значением приводит к ошибке при попытке ввести вещественное значение в целочисленную переменную или при наборе недопустимого символа в числе.


В Си основные неприятности форматного ввода (функция scant) связаны с попыткой указать в списке ввода не адрес переменной, а ее имя:


scanf("%d",x); //правильно было бы scanf("%d",&x);


Компилятор ТС/ВС такую ошибку, к сожалению, не замечает и преобразует имя х в какой-то фантастический адрес. Последующую работу программы в этом случае предсказать трудно. Не обращает внимания компилятор Си и на несоответствие между спецификатором формата и типом переменной из списка ввода. Всего этого можно избежать, используя потоковый ввод:


cin » х;


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


Вывод числовых результатов


Наиболее приятный вид имеет числовая информация, организованная по табличному типу — в виде колонок фиксированной ширины, в которых одноименные числовые разряды располагаются друг под другом (единицы -под единицами, десятки — под десятками, сотни — под сотнями и т. д.). При этом, в частности, более рационально используется площадь экрана, что достигается за счет управления форматами выводимых данных.


В QBasic для этой цели служит оператор PRINT USING, совмещающий в себе и строку с описанием формата и список выводимых значений:


PRINT USING "А=##.## B=### С=#.####^^^^"; А,В,С


Аналогичные средства имеются и в Си:


printf ("A=%6.3f B=%3d С=%10.4е",А,В,С);


При выводе в поток, когда к Си-программе подключаются заголовочные файлы iostream.h и iomanip.h, тоже существует возможность управлять форматом выводимых данных:


cout << "А=" << setw(6) << setprecision(5) << А;


Несколько скромнее выглядит управление форматом в Паскале:


write('А=',А:6:3,"В=',В:3,'С=',С:10);


Среди форматных спецификаторов в Си есть дополнительные возможности, отсутствующие в QBasic и Паскале. Например:


printf("%4x %6о",х,у);


Приведенные здесь спецификаторы позволяют вывести значения целочисленных переменных х и у соответственно в виде шестнадцатеричного числа с четырьмя цифрами и восьмеричного числа с шестью цифрами.


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


Задачи,советы и ответы


Задание 2.01. Ввод и вывод целочисленных данных


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


Совет 1


Предположим, что вы будете работать с двухбайтовыми целыми числами. Тогда для размещения самого длинного числа потребуется не менее 7 позиций (число —32 768 занимает 6 позиций плюс пробел между числами). Если перед числом необходимо вывести его номер, то дополнительно потребуются еще, как минимум, 3 позиции (2 под номер из диапазона [1,20] и разделитель между номером и числом, например в виде двоеточия). Таким образом, для компактного вывода на каждое число вместе с его номером можно отвести 10 позиций, что хорошо согласуется с длиной строки на дисплее. Если бы оказалось, что длина строки не кратна ширине колонки, то часть последнего числа была бы автоматически перенесена на следующую строку.


Совет 2


Как организовать ожидание в программе до нажатия какой-либо клавиши? В QBasic для этой цели подойдет системная переменная INKEY$. Достаточно присвоить ее значение какой-либо символьной переменной, например А$, и организовать бесконечный цикл до тех пор пока длина значения А$ перестанет отличаться от нуля:


А$=""


М10 : A$=INKEY$ ; IF А$="" THEN GOTO M10


Можно воспользоваться и другим приемом — включить в программу оператор ввода в какую-либо переменную символьного типа. Такая переменная предпочтительнее числовой, т. к. в нее можно ввести пустое значение, нажав только клавишу . Кроме того, набор любого отображаемого символа не приведет к ошибке.


В Си временный приостанов до нажатия какой-либо клавиши организуют с помощью функции getch.


В Паскале можно организовать бесконечный цикл, аналогичный приведенному выше варианту для QBasic, с помощью логической функции KeyPressed:


while not KeyPressed;


Аналогом ввода пустого значения INPUT А$ в QBasic в Паскале является использование процедуры read/readln без параметров. В этом случае для проталкивания программы потребуется нажать клавишу .


Программа 2_01.bas


RЕМ Ввод, вывод и суммирование 20 целых чисел


DIM A(20)


F$="##:###### "


PRINT "Введите 20 чисел, по одному в строке"


FOR 1=0 ТО 19: INPUT A(I): S=S+A(I): NEXT I


FOR 1=0 TO 19: PRINT USING F$;I+1;A(I); : NEXT I


INPUT A$


FOR 1=0 TO 19: PRINT USING F$;I+1;A(I): NEXT I


PRINT " —


PRINT USING " ######"; S


END


Программа 2_01.с


/* Ввод, вывод и суммирование 20 целых чисел */

#include


#include


main() {


int j,s=0,a[20];


clrscr();


printf("Введите 20 чисел, по одному в строке\n"


for(j=0; j<20; j++) { scanf("%d",&a[j]); s+=a[j]; }


for(j=0;j<20;


printf("%2d:%-6d ",j+l,a[j]>; for(j=0;j<20; j++)


printf("\n%2d:%6d ",j+l,a[j]) ; printf("\n -------\n%9d",s);


getch();


Программа 2_01.pas


program io_numbers;


{ Ввод, вывод и суммирование 20 целых чисел }


uses Crt;


var


j, s:integer;


a:array [1..20] of integer; begin


s: =0 ;


clrscr;


writeln('Введите 20 чисел, по одному в строке"!


for j:=1 to 20 do


begin readln(a[j]); s:=s+a[j]; end;


for j:=l to 20 do write(j:2,':',a[j]:6,' ');


writeln('Нажмите любую клавишу';


readkey; clrscr;


for j:=l to 20 do writeln(j:2,':',a[j]:6,' ');


writeln(' --------');


writeln (s: 9).;


readln; end.


Задание 2.02. Ввод и вывод вещественных данных


Самостоятельно выполнить задание 2.01 в предположении, что вводимые числа вещественные и имеют две значащие цифры в дробной части.


Задание 2.03. Преобразование десятичного числа в системы С основанием 2, 8, 16


Ввести длинное неотрицательное число. Вывести его в двоичном, восьмеричном и шестнадцатеричном представлении.


Совет 1 (QBasic)


Предлагается воспользоваться стандартными функциями ост? и НЕХ$, преобразующими числовой аргумент в строку с его представлением в соответствующей системе счисления. Для двоичного представления можно распечатать восьмеричные цифры их трехразрядными двоичными эkвивaлeнтawш


Совет 2 (Си)


Предлагается воспользоваться библиотечной функцией Itoa, преобразующей свой первый аргумент из машинного представления числа в строку, заданную вторым аргументом. Третий аргумент этой функции определяет основание системы счисления, в которую конвертируется исходное число. Вообще говоря, восьмеричный и шестнадцатеричный эквиваленты числа проще вывести, используя спецификатор формата %о и %х. Для вывода двоичного представления числа можно было бы организовать цикл со сдвигом числа на один разряд влево (N = N « 1;), пробой старшей цифры (N & 0x8000) и выводом соответствующего символа в зависимости от результата сравнения.


Совет 3 (Паскаль)


В этом языке отсутствуют какие-либо системные функции или процедуры, отмеченные выше. Поэтому единственным средством будет лобовое преобразование путем последовательного деления исходного числа на основание соответствующей системы и запоминание получающихся остатков в некотором массиве. Так как длинное число занимает в памяти ЭВМ 4 байта, максимальный размер массива для хранения цифр числа в соответствующем представлении не должен превышать 32 элемента. Небольшие проблемы могут возникнуть при выводе шестнадцатеричных цифр от А до F. Из них придется вычитать 10 и добавлять полученную разницу к коду буквы А.


Программа 2_03.bas


REM Перевод числа в системы с основаниями 2, 8 и 16


CLS


INPUT "Введите положительное число : ",N&


А$=ОСТ$(N&)


PRINT "В двоичном представлении ";N&;"= ";


FOR k=l TO LEN(A$)


B$=MID$(A$,k,1) : ' Выделение очередной восьмеричной цифры


SELECT CASE B$


CASE "О": IF k=l THEN PRINT ""; ELSE PRINT "000";


CASE "1": IF k=l THEN PRINT "1"; ELSE PRINT "001";


CASE "2": IF k=l THEN PRINT "10"; ELSE PRINT "010";


CASE "3": IF k=l THEN PRINT "11"; ELSE PRINT "01l";


CASE "4": PRINT "100";


CASE "5": PRINT "101";


CASE "6": PRINT "111";


CASE "7": PRINT "111";

END SELECT

NEXT k

PRINT


PRINT "В восьмеричном представлении ";N&;"= ";OCT$(N&)

PRINT "В шестнадцатеричном представлении ";N&;"=";HEX$(N&)

END


Программа 2_03a.bas

REM Перевод числа в системы с основаниями 2, 8 и 16
CLS


INPUT "Введите положительное число : ",n&


а$=ОСТ$(п&) : ' Перевод в восьмеричную систему


IF n&=0 THEN


PRINT "Это число в любой системе равно 0" STOP END IF PRINT "В двоичном представлении ";п&;"= ";


B$=LEFT$(а$,1}: : ' Выделение очередной восьмеричной цифры SELECT CASE B$


SELECT CASE B$
CASE "0": PRINT "";
CASE "1": PRINT "1";
CASE "2": PRINT "10";
CASE "3": PRINT "11";
CASE "4": PRINT "100";
CASE "5": PRINT "101";
CASE "6": PRINT "111";
CASE "7": PRINT "111";
END SELECT
FOR K = 2 TO LEN(a$)
B$ = MID$(a$, K, 1)
SELECT CASE B$
CASE "0": PRINT "000";
CASE "1": PRINT "001";
CASE "2": PRINT "010";
CASE "3": PRINT "011";
CASE "4": PRINT "100";
CASE "5": PRINT "101";
CASE "6": PRINT "111";
CASE "7": PRINT "111";
END SELECT
NEXT K
PRINT


PRINT "В восьмеричном представлении ";n&;"= ";OCT$(n&)

PRINT "В шестнадцатеричном представлении ";n&;"= ";HEX$(n&) END

END

Программа 2_03.с


/* Перевод числа в системы счисления с основаниями 2, 8 и 16 */

#include

#include

#include


main()

{


long N;

char a[33];

clrscr();


printf("Введите положительное число : ") ;

scanf("%ld",&N);

if(N==0) {


printf("\n Такое число в любой системе = 0") ;

exit(1);

}


ltoa(N,a,2);

/* перевод в двоичную систему */

printf("\n B двоичном представлении %ld = %s",N,a);

ltoa(N,a,8);

/* перевод в восьмеричную систему */

printf("\nВ восьмеричном представлении %ld = %s",N,a);

ltoa(N,a,16);

/* перевод в шестнадцатеричную систему */

printf("\n В шестнадцатеричном представлении %ld = %s",N,a);

getch();

}


Программа 2_03.pas


program _2_8__16;


{ Перевод числа в системы с основаниями 2, 8 и 16 }


uses crt; var


N1,N:longint;


a:array [0..31] of byte;


j,k:byte;


s:char; begin


clrscr;


write('Введите положительное число : ');

readln(N);

if N=0 then begin


writeln('Такое число в любой системе = 0');


exit;

end;

N1:=N;


for j:=0 to 31 do

a[j]:=0;

while Nl<>O do


begin


a[j]:=N1 mod 2; {цикл выделения двоичных цифр}


dec(j);

N1:=N1 div 2;

end;


write('В двоичном представлении ',N,'=');

for k:=j+l to 31

do write(a[k]:1);

writeln;

N1:=N;


for j:=0 to 10 do a[j]:=0;

while N1<>0 do begin


a[j]:=Nl mod 8; {цикл выделения восьмеричных цифр)


dec(j);

N1:=N1 div 8;


end;


write (' В восьмеричном представлении ',N,'=');

for k:=j+l to 10

do write(a[K]:i);

writeln; N1:=N;

for j:=0 to т 7 do a[j];=0;


while N1<>0 do begin


a[j]:=N1 mod 16;


dec(j);


N1:=N1 div 16;{ цикл выделения шестнадцатеричных цифр}


end; write('В шестнадцатеричном представлении ',N,'=');


for k:=j+l to 7 do begin


if a[k]<10

then s:=chr(ord('0')+a[k]}

else s:=chr(ord('A')+a[k]-10);

write (s) ;

end;

readln;

end.


Задание 2.04. Преобразование десятичного числа в Систему с основанием r


Составить функцию num_to_str (пшп, г), возвращающую в качестве своего значения строку с представлением натурального числа num в системе счисления с основанием г. Предполагается, что число num в памяти компьютера представлено 4-байтовым целым, а основание r принадлежит диапазону |2, 16]. Для обозначения цифр, превосходящих 9, рекомендуется воспользоваться латинскими буквами А, в, ... , F.


Совет 1 (общий)


Так как основание системы может быть любым, необязательно совпадающим с наиболее распространенными вариантами (r = 2,8,16), то наиболее универсальным способом перевода остается последовательное деление исходного числа на основание с запоминанием целочисленных частных и остатков. Небольшое осложнение будет вызвано преобразованием двухзначных остатков (при r > 10) в односимвольную "цифру". Однако подход к решению этого вопроса уже был продемонстрирован в предыдущей программе на Паскале. Очередной остаток q надо сравнить с 10 и, в зависимости от исхода сравнения, либо преобразовывать в символ полученную цифру, либо добавлять разницу q-10 к коду буквы А. Вторая тонкость заключается в том, что предлагаемый способ перевода позволяет получать цифры разложения справа налево, начиная с младшей. Поэтому перед выдачей результата полученную строку придется перевернуть.


Совет 2 (QBasic)


Вы можете выбрать один из двух способов описания типов данных — более современный, хотя и несколько более длинный, с использованием переменных,


описанных как AS LONG, AS STRING, AS INTEGER, или более старомодный с добавками %, &, $ в конце имени переменной. Возможность "складывать" символьные значения в любом порядке позволяет избежать инвертирования результирующей строки. Для этого вместо оператора А$ = A$ + CIF$ удобнее воспользоваться левосторонней конкатенацией А$ = CIF$+A$.


Совет 3 (Си)


Выбор длины строки, в которой будет накапливаться промежуточный или окончательный результат, определяется самым длинным разложением при r = 2 (т. е. 32 разряда плюс еще один байт под признак конца строки). Заводить две строки под правое и левое представление, наверное, не стоит. Проще произвести перестановку симметричных байтов (первый с последним, второй с предпоследним и т. д.) в одной строке. Для выполнения этой операции придется ввести счетчик количества цифр или прибегнуть к библиотечной функции strlen из раздела string, h.


Программа 2_04.bas


REM Перевод числа в систему с основанием r


DECLARE FUNCTION NToStr$(NUM&,R%)


CLS


INPUT "Введите натуральное число : ",N&


PRINT "Его представление в разных системах счисления таково : "


FOR J%=2 TO 16


PRINT "по основанию ";

J%,N&;"= ";NToStr$(N&,J%) NEXT J% END


FUNCTION NToStr$(NUM&,R%) A$="": MS=NUM& DO


CIF=M& MOD R% : ' Выделение очередной цифры

IF CIF<10 THEN


A$=CHR$(ASC("0")+CIF)+A$ : ' Замена цифры кодом ASCII ELSE


A$=CHR$(ASC("A")+CIF-10)+A$ END IF


М&=(М&-CIF)/R% : ' Исключение обработанной цифры


LOOP UNTIL M&=0 NToStr$=A$ END FUNCTION


Программа 2_04.с


/* Перевод числа в систему с основанием r */

#include


# include


char *num_to_str (long num, char r) ;


void main (void) {


long N;


char j ;


printf ("\n Введите натуральное число ");


scanf ("%ld",&N);


printf ("Его представление в разных системах счисления таково :\n")


for(j=2; j<17; j++)


printf ("\n по основанию %2d = %s", j ,num_to_str (N, j ) ) ;


getch ( ) ;


}


char *num_to_str(long num, char r) {


static char a[33];

char cif, k, count=0; do {


cif=num % r;

/* Выделение очередной цифры */

if(cif<10) a[count++]='0'+cif;

/* Замена цифры кодом ASCII, если цифра меньше 10 */


else a[count++]='A'+cif-10;

/* Замена цифры кодом ASCII, если цифра больше 9 */


num=num/r;

/* Исключение обработанной цифры */ }


/* Цикл изменения порядка цифр в массиве а */

while (num != 0);

a[count--]=0х0;

for(k=0; k<=count/2; k++)


{ cif=a[count-k]; a[count-k]=a[k]; a[k]=cif; } return a; }


Программа 2_04.pas


program num to pos;


{ Перевод числа в систему с основанием г }


var


N:longint;


j:byte;


function num_to_str(num: longint;r:byte):string; var


a:string[33];


cif,k:byte; begin


a:='';


repeat


cif:=num mod r; { Выделение очередной цифры }

if (cif<10) then a:=chr(48+cif)+a

{ Замена цифры кодом ASCII, если цифра меньше 10 }


else a:=chr(65+cif-lO)+a;

{ Замена цифры кодом ASCII, если цифра больше 9 }


num:=num div r; { Исключение обработанной цифры }


until (num=0);


num_to_str:=а; end; begin


write('Введите натуральное число - ');


readln(N);


writelnf'Ero представление в разных системах счисления таково :']


for j :=2 to 16 do


writeln('no основанию ',j:2,' = ',num_to_str(N,j));


readln; end.


Задание 2.05. Симметричное разложение с наименьшим основанием


Дано натуральное число N (N < зоооо). Найти систему счисления с наименьшим основанием Pmin, в которой N имеет симметричное представление. Например,


ДЛЯ N=0 Pmin-2 (910 = 10012),


ДЛЯ N-1000 Emin=S (100010 - 13319)


Программа должна запрашивать число N, выдавать Pmin и значения


цифр в представлении числа N в этой системе (цифры можно выводить в виде обычных десятичных чиселл).


Cовет 1(oбщий)


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


Второй очевидный факт заключается в том, что всегда найдется такая система счисления, в которой разложение любого числа N будет симметричным. Такой системой, в частности, является система с основанием N-1, т. к. в ней число N выглядит как 11. Поэтому остается только организовать цикл по основаниям систем от 2 до N-I и, как только будет найдено симметричное разложение, прекратить перебор.


Совет 2 (общий)


Разумно организовать в программе две внешние функции — perevod (перевод исходного числа в систему с заданным основанием) и proba (проверка симметрии полученных цифр). Первая функция может быть построена по аналогии с функцией num_to_str, с той лишь разницей, что цифры, получаемые в процессе перевода, надо запоминать в массиве.


Совет 3 (QBasic)


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


Программа 2_05.bas


RЕМ Поиск симметричного разложения числа


DECLARE FUNCTION perevod!(n%,p%,a%())


DECLARE FUNCTION proba! (a%(),k%)


DIM a%(16)


CLS


INPUT "Введите число из диапазона [0,30000] : ",n%


FOR p%=2 TO n%-l


k%=perevod(n%,p%,a%()) : ' Перевод в р-ричную систему

IF proba(a%(), k%) о 0 THEN


PRINT "Симметричное разложение с минимальным основанием

FOR i = 0 ТО k% - 1


PRINT TAB(0);а%(i);"*";р%; "^";k%-i;"+";


NEXT i


PRINT :

PRINT a% (0);"*";p%;"^";0


END

END IF

NEXT p%

END


FUNCTION perevod (n%,p%,a%())


REM Перевод числа n в систему с основанием р


RЕМ Цифры р-ричного числа запоминаются в массиве а


m%=n%


FOR i=0 TO 15


a%(i)=m% MOD p%


m%=(m%-a%(i))/p%


IF m%=0 THEN perevod=i: EXIT FUNCTION

NEXT i

END FUNCTION


FUNCTION proba (a%(),k%)


REM Анализ числа, представленного k цифрами в массиве а


REM Если число - палиндром, то proba=l


proba=l


FOR i=0 TO k%/2


IF a% (i)0a% (k%-i) THEN proba=0: EXIT FUNCTION

NEXT i

END FUNCTION


Программа 2_05.с


/* Поиск симметричного разложения числа */


#include


#include


int perevod(int n, int p, int *a);


int proba(int *a, int k);


int i ;


main() {


int k,p,N,a[16];


clrscr () ;


scanf("%d",&N);


for (p=2; p

k=perevod(N, p, a); /* Перевод в р-ричную систему */


if (proba(a,k)==0) continue;


printf("Хпминимальное основание = %d\n",p);


for(i=0; i<=k; i++)

printf("%d ",a[i]);


break;


getch(); }


int perevod(int n,int p,int *a) /* Перевод числа п в систему с основанием р


Цифры р-ричного числа запоминаются в массиве а */


for(1=0; 1<1б; 1++)


a[i]=n % р; n=n/р;


if(n==0) return i;


}


int proba (int *a, int k)


/* Анализ числа, представленного k цифрами в массиве а


Если число - палиндром, то proba=l */ {


for(i = 0; i <= k/2; 1++)


if(a[i] != a[k-i]) return 0; return 1 ;


Программа 2_05.pas


program min_base;


{ Поиск симметричного разложения числа }


uses Crt;


var


i, k, p,N: integer;


a:array [0..15] of integer;

function perevod(n,p:integer) :integer;

{ Перевод числа n в систему с основанием р


Цифры р-ричного числа запоминаются в массиве а}


begin


for i:=0 to 15 do

begin


a[i]:=n mod p;

n:=n div p;

if n=0 then


begin perevod:=i;

exit;

end;

end;

end;


function proba(k:integer):integer;

{ Анализ числа, представленного k цифрами в массиве а


Если число - палиндром, то proba=l }

begin


for i:=0 to k div 2 do

if a[i]<>a[k-i] then

begin proba:=0;

exit;

end;

proba:=1;

end;

begin clrscr;


writeln('Поиск симметричного разложения с минимальным основанием');

writeln('Введите число');

readln(N);

for p:=2 to N do

begin


k:=perevod(N,p);

if proba(k)=0 then continue;

writeln('минимальное основание = ',p);

for i:=0 to k do writeln(a[i]);

break;

end;

readln;

end.


Задание 2.06. Суммирование десятичных цифр


Составить функцию sum_dig(n), аргументом которой является длинное целое число. Возвращаемое значение должно быть равно сумме десятичных цифр числа n.


Совет 1 (общий)


Обратите внимание на ситуацию, когда аргумент отрицателен. Остаток от де-ления отрицательного числа на 10 будет также отрицательным.


Совет 2 (OBasic)


Будьте внимательны при определении очередного частного от деления числа на 10. QBasic производит округления, и результат деления, например, целого числа 15 на целое число 10 даст в частном не 1, а 2.


Совет 3 (Си, Паскаль)


Обратите внимание на то, что циклы do (Си) и repeat (Паскаль) требуют противоположных условий выхода из цикла.


Программа 2_06.bas


RЕМ Суммирование десятичных цифр числа


DECLARE FUNCTION SUMDIG (N&)


CLS


INPUT "Введите целое число";М&


K=SUMDIG(M&)


PRINT "Сумма его цифр = ";К


END


FUNCTION SUMDIG(N&)


IF N&<0 THEN N&=-N& : ' Смена знака у отрицательного числа


RESULT=0


DO


RESULT=RESULT+(N& MOD 10&) : ' Накопление суммы цифр

N&=(N&-(N& MOD 10&))/10& : ' Удаление обработанной цифры


LOOP WHILE N&<>O


SUMDIG=RESULT


END FUNCTION


Программа 2_06.с


/* Суммирование десятичных цифр числа */

#include

int sum_digits(long N);

main()


}


long M;


printf ("\n Введите целое число: ");

scanf ("%ld", &M) ;


printf ("\n Сумма его цифр = %d", sum_digits (M) ) ;

getch ( ) ; }


int sum_digits (long N) {


int Result=0;


N=labs (N) ; /* Смена знака у отрицательного числа */

do {


Result=Result+N%10; /* Накопление суммы цифр */

N=N/10; /* Удаление обработанной цифры */ }


while (N != 0) ;

return Result;


}


Программа 2_06.pas


program sumdigits;


{ Суммирование десятичных цифр числа }


var


M:longint;


function sum_digits (N: longint) : integer;


const


Result : integer=0 ;

begin


if N<0 then N:=-N;

{ Смена знака у отрицательного числа } repeat


Result :=Result+N mod 10; { Накопление суммы цифр }

N:=N div 10; { Удаление обработанной цифры }

until N=0;

sum_digits : =Result;

end;


begin


write ( ' Введите целое число : ' ) ;

readln (M) ;


writeln('Сумма его цифр =',sum_digits(M)! readln;


end.


Задание 2.07. "Счастливый" Сияет


Составить логическую функцию luck(n), аргументом которой является число п из диапазона [0, 999999]. Функция должна возвращать значение true (Паскаль) или i (Си, QBasic), если ее аргумент представлен "счастливым" числом, у которого суммы трех старших и трех младших цифр совпадают.


Программа 2_07.bas


REM Анализ "счастливого" билета

DECLARE FUNCTION LUCK(M AS LONG)

INPUT "Введите номер билета ";N& IF LUCK(N&)=1 THEN


PRINT "Радуйтесь - счастливый" ELSE


PRINT "Нет счастья в жизни" END IF END


FUNCTION LUCK(M AS LONG)


REM Подсчет и сравнение сумм старших и младших цифр М


REM Если суммы совпадают LUCK=1


DIM A(6)


LUCK=0


IF M<0 OR M>999999 THEN


PRINT "luck : недопустимый аргумент":

EXIT FUNCTION

END IF

FOR i=0 TO 5


A(I)=M MOD 10 : ' Выделение очередной цифры


M=(M-A(I))/10 : ' Удаление обработанной цифры

NEXT I


IF (A(0)+A(1)+A(2)=A(3)+A(4)+A(5)) THEN LUCK=1

END FUNCTION


Программа 2_07.с


/* Анализ "счастливого" билета */

#include

int luck(long M);


main() {


long N;


printf("\n Введите номер билета ");


scanf("%ld",&N);


if (luck(N)==l)


printf("\n Радуйтесь - счастливый");

else


printf("\n Нет счастья в жизни"); getch(); }


int luck(long M)

/* Подсчет и сравнение сумм старших и младших цифр М


Если суммы совпадают luck=l*/ {


int i ; char a[6];


if((M<0) || (M>999999)) {


printf("\nluck : недопустимый аргумент");

exit(0); }


for(i=0; i<6;.i++) {


a[i]=M % 10; /* Вьщеление очередной цифры */

M=M/10; /* Удаление обработанной цифры */

}


if(a[0]+a[l]+a[2]=a[3]+a[4]+a[5]> return 1;

return 0; }


Программа 2_07.pas


program lucky_ticket;


{ Анализ "счастливого" билета


var


N:longint;


function luck(M:longint):boolean;

{ Подсчет и сравнение сумм старших и младших цифр М


Если суммы совпадают luck=true }

var


i:integer;


a:array [1..6] of byte;

begin


if (M<0) or (M>999999) then begin


writeln('luck : недопустимый аргумент');

exit;

end;


for i:=l to 6 do

begin


a[i]:=M mod 10; { Выделение очередной цифры }

M:=M div 10; { Удаление обработанной цифры }


end;


luck:=(a[l]+a[2]+a[3])=(а[4]+а[5]+а[6]);

end;

begin


writeln('Введите номер билета');


readln(N);


if luck(N) then


writeln('Радуйтесь - счастливый') else


writelnt'HeT счастья в жизни');

readln;

end.


Задание 2.08. Количество различных цифр в десятичном числе


Составить функцию num_digits (n), аргументом которой является длинное целое число. Возвращаемое значение должно быть равно количеству различных цифр в десятичной записи п. Например: num_digits (1998) =3.


Совет 1 (общий)


Предлагается завести массив из 10 счетчиков, каждый из которых будет подсчитывать количество своих цифр — первый счетчик считает нули, второй —


единицы и т. д. Вначале массив счетчиков обнуляется, а после выделения всех цифр числа проверяется, сколько счетчиков хранят ненулевые значения. Вообще говоря, можно не заниматься подсчетом количества появлений каждой цифры —достаточно фиксировать сам факт появления той или иной цифры.


Совет 2 (Си, Паскаль)


Обратите внимание на различное оформление функций num_digits на Си и Паскале. Локальные переменные в функциях на Си, которым присваиваются начальные значения, при повторных обращениях к функциям инициализируются заново. В процедурах и функциях Паскаля такая инициализация производится только один раз, поэтому повторный вызов может привести к неверным результатам.


Программа 2_08.bas


RЕМ Определение количества различных цифр в числе


DECLARE FUNCTION NumDig!(N&)


CLS


INPUT "Введите число : ", N&


PRINT "Количество разных цифр в его записи = ";NumDig(N&)


END


FUNCTION NumDig(N&)


REM Выделение и подсчет количества разных цифр в числе N


DIM d(10) : ' Массив для фиксации обнаруженных цифр


КЕМ При вызове функции d(i)=0


IF N&<10 THEN NumDig=l: EXIT FUNCTION


DO


k%=N& MOD 10 : ' Выделение очередной цифры

d(k%)=d(k%)+l : ' Подсчет количества цифр, равных k

N&=(NS-k%)/10 : ' Удаление обработанной цифры


LOOP UNTIL N&=0


FOR k%=0 TO 9 : ' Цикл подсчета количества обнаруженных цифр

IF d(k%)<>0 THEN s=s+l : ' Если d(i)=0, цифры i не было


NEXT k%


NumDig=s


END FUNCTION


Программа 2_08.с


/* Определение количества различных цифр в числе */

#include

#include


int num_digits(long N);


main() {


long N;


printf("\n Введите число - ");


scanf("%ld",&N);


printf("\Количество разных цифр в его записи = %d ",


num_digits(N));

getch(); }


int num_digits(long N)


/* Выделение и подсчет количества разных цифр в числе N */ {


char d[10]={0,0,0,0,0,0,0,0,0,0}; /* Массив счетчиков цифр */

int k,s=0;

if(N<10) return 1;

while (N) {


d[N % 10]++; /* Выделение и учет очередной цифры */

N=N/10; /* Удаление обработанной цифры */ }


/* Цикл подсчета количества обнаруженных цифр */

for(k=0; k<10; k++)

if(d[k]) s++;

return s; }


Программа 2_08.pas


program NumDigits;


{ Определение количества различных цифр в числе }


var


N:longint;


function num_digits(N:longint):byte;


{ Выделение и подсчет количества разных цифр в числе N } var


d:array [0..9] of byte; { Массив счетчиков }

s,k:byte;

begin


if N<10 then num_digits:=1


else begin


for k:=0 to 9 do d[k]=0; { Сброс счетчиков }

s: =0 ;


while N<> 0 do begin


inc(d[N mod 10]); { Выделение и учет очередной цифры }

N := N div 10; { Удаление обработанной цифры }

end;


{ Цикл подсчета количества обнаруженных цифр }

for k:=0 to 9 do

if(d[k]<>0) then inc(s);

num_digits:=s;

end;

end;


begin


write('Введите число : ');


readln(N);


writeln('Количество разных цифр в его записи = ',num_digits(N));


readln;

end.


Задание 2.09. Определение цифры в заданной позиции


Составить функцию digit_in_pos (n,i), аргументами которой являются длинное целое число n и номер i позиции цифры в десятичном представлении n. Отсчет номеров позиций ведется справа налево от 0 и соответствует "весу" цифры (степени основания), с которым цифра входит в число. Например:


n=1985


в 0-й позиции находится цифра 5;


в 1-й позиции находится цифра 8;


во 2-й позиции находится цифра 9;


в 3-й позиции находится цифра 1;


Функция digit_in_pos должна возвращать цифру, расположенную в 1-й позиции числа п.


Программа 2_09.bas


RЕМ Анализ цифр в каждой позиции заданного числа

DECLARE FUNCTION DIGINPOS(N AS LONG,J AS INTEGER)


INPUT "Введите целое число: ";М&

FOR K%=0 ТО 9


DIGIT=DIGINPOS(M&,К%)


PRINT "В позиции ";К%;" находится ",DIGIT NEXT K%

END


FUNCTION DIGINPOS(N AS LONG,J AS INTEGER)


REM Определение десятичной цифры числа N в позиции j


N1&=N


FOR K%=0 TO J


RESULT=N1& MOD 10


N1&=N1&-RESULT)/10 NEXT K%


DIGINPOS=RESULT

END FUNCTION


Программа 2_09.с


/* Анализ цифр в каждой позиции заданного числа */


#include


int digit_in_pos(long N,int j);


main () {


long M;


int k;


printf("ХпВведите целое число: ");


scanf("%ld",&M);


for(k=0; k<10; k++)


printf("\nB позиции %d находится %d",k,digit_in_pos(M, k)) ;


getch(); }


int digit_in_pos(long N,int j)


/* Определение десятичной цифры числа N в позиции j */ {


int Result,k;


for (k=0; k<=j; k++) {


Result=N % 10; N=N/10;


}


return Result; }


Программа 2 09.pas


program DigitlnPos;


{ Анализ цифр в каждой позиции заданного числа }


var


M:longint;


k:integer;


function digit_in_pos(N:longint;j:integer):integer;

{ Определение десятичной цифры числа N в позиции j }

var


Result,k:integer;

begin


for k:=0 to j do


begin


Result:=N mod 10;

N:=N div 10;


end;


digit_in_pos:=Result;

end;

begin


writeln('Введите целое число:');


readln(M);


for k:=0 to 9 do


writeln('В позиции ',k,' находится ',digit_in_pos(M,k));


readln;

end.


Задание 2.10. Генерация чисел с заданной суммой цифр


Составить программу, которая выдает все числа из диапазона [0, 999], сумма цифр которых равна вводимому числу N (о < N < 27).


Программа 2_10.bas


REM Генерация чисел с заданной суммой цифр


INPUT "Введите число в диапазоне от 0 до 27 : ",n


PRINT "Список чисел, сумма цифр которых равна ";n;" :"

FOR a2%=0 ТО 9

FOR a1%=0 TO 9

FOR a0%=0 TO 9


IF a2%tal%+aO%=n THEN


PRINT USING "####";100*a2%+10*al%+a0%;


END IF


NEXT a0%,al%,a2%

END


Программа 2_10.c


/* Генерация чисел с заданной суммой цифр */

#include

#include


main () {


int a2,al,a0,n;


printf("\n Введите число в диапазоне от 0 до 27 : ");


scanf("%d",&n);


printf("\n Список чисел, сумма цифр которых равна %d :\n",n);


for(a2=0; a2<10; а2++)

for(al=0; al<10; al++)

for(a0=0; a0<10; a0++)


if(a2+al+a0==n) printf("%4d",100*a2+10*al+a0);


getch(); }


Программа 2_10.pas


program numbers;


{ Генерация чисел с заданной суммой цифр }


var


а2,al,aO,n:integer; begin


write('Введите число в диапазоне от 0 до 27 : ');


readln(n);


writeln('Список чисел, сумма цифр которых равна ',n, ' :');


for a2:=0 to 9 do


for al:=0 to 9 do

for a0:=0 to 9 do


if (a2+al+a0)=n then write(100*a2+10*al+a0:4);

readln;

end.

  1   2   3   4


Глава 2. Работа с числовыми данными
Учебный материал
© nashaucheba.ru
При копировании укажите ссылку.
обратиться к администрации