Консультация № 160325
12.02.2009, 20:38
60.00 руб.
0 22 2
Пацаны, помогите с задачей: Написать программу вычитания целых 16-ричных чисел(через строки). Заранее спасибо.

Обсуждение

Неизвестный
12.02.2009, 21:58
общий
А не пацаны могут помочь? Вопрос: значит, не нужно преобразовывать строку в число? Каково основание чисел: двоичные числа? десятеричные? ....
Если 16-ричные, значит, двоичные?
Неизвестный
12.02.2009, 22:48
общий
16- ричная система счисления, не двоичная. Строки задаются с учетом особенностей системы, определяем большее из 2 чисел, вычитаем, вывод в той же системе((((
Неизвестный
12.02.2009, 22:52
общий
1) подпрограмма проверки ввода числа
2)выравнивание длин
3)нахождение большего
4)непосредственно вычисление
5) вывод
Неизвестный
12.02.2009, 23:09
общий
это ответ
Здравствуйте, Челпанников Алексей Алексеевич!
Да шутил я, пока писал
Вот посмотрите в приложении. Тестировал, вроде работает правильно
Если будут вопросы, спрашивайте в минифоруме

Приложение:
uses CRT;

function InputBinary: String;
var buf: String; ch: char;
x, y: Integer;
begin
Write('Введите бинарную строку: ');
x := WhereX; y:=WhereY;
buf := '';
repeat
gotoxy(x + length(buf), y);
ch := ReadKey;
case ch of
'0','1': buf := buf + ch;
#8: {backspace} if length(buf) >= 1 then delete(buf, length(buf), 1);
end;
gotoXY(x, y); write(buf,' ')
until (ch = #13) or (ch = #27) or (length(buf) >= 16); {ENTER или Esc}
WriteLn;
if buf = '' then buf := '0';
InputBinary := buf
end;

function Convert(num: String): Integer;
var i, n, dig: Integer;
begin
n := 0;
dig := 1;
while length(num) < 16 do num := '0' + num;
for i:= length(num) downto 1 do
begin
n := n + (ord(num[i])-48)*dig;
dig := dig * 2;
end;
Convert := n
end;


VAR
num1, num2: String;
k, m: Integer;
BEGIN

num1 := InputBinary;
num2 := InputBinary;

{доводим длину до стандартной 16}
writeLn(num1,' ',num2);
while length(num1) < 16 do num1 := '0' + num1;
while length(num2) < 16 do num2 := '0' + num2;
WriteLn('десятичная запись: ',Convert(num1),' - ', Convert(num2));
WriteLn(num1,#10#13,'-',#10#13,num2,#10#13,'-------------');

{вычитание. Пишу как можно проще, то-есть, реализую пошагово действия ручные}
for k := 16 downto 1 do
case num1[k] of
'0': if num2[k] = '1' then
begin
num1[k] := '1';
m := k -1;
while (m >= 1) do begin
if num1[m] = '1' then
begin num1[m] := '0'; break end
else num1[m] := '1';
dec(m)
end
end;
'1': if num2[k] = '1' then num1[k] := '0';
end;

WriteLn(num1);
WriteLn(' Результат в десятичной форме: ', convert(num1));
END.
Неизвестный
12.02.2009, 23:14
общий
1) Нет подпрограммы проверки, есть подпрограмма правильного ввода
2) выравнивание длин, для упрощения есть;
3) не находим большее, а просто и тупо вычитаем из первого второе
---
СЕЙЧАС подумал, что если процедуре преобразования Convert передать строку более 16 символов - будет неправильно работать.
В программе передается правильная строка, которая вводится с помощью процедуры-функции InputBunary.
Нужно предусмотреть и неправильный случай. По-моему, ничего делать не надо, а только предупредить, что ввод неправильный и завершить работу
Неизвестный
12.02.2009, 23:24
общий
Уважаемый Профессор Boriss,

WriteLn(num1,#10#13,'-',#10#13,num2,#10#13,'-------------'); В этой строке ошибка ввода: неверное выражение, в теле цикла головной программы. И эти #, что это...? Хм... Работаю в Паскаль авс. Сам текст программы тяжеловат, не могу сам понять почему;(
Неизвестный
12.02.2009, 23:32
общий
Да, и если можно без GOTO.
давно
Старший Модератор
31795
6196
12.02.2009, 23:35
общий
Челпанников Алексей Алексеевич:

А чем 16 отличается от 2, только выводом и вводом допустимых значеий.
Как было 1111=F, так оно и остается, 16--я система это короткая запись двоичного кода.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
12.02.2009, 23:38
общий
Архитектуру я знаю, а вот как это на Паскале(((( Эх
давно
Старший Модератор
31795
6196
12.02.2009, 23:40
общий
Работаю в Паскаль авс

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

давно
Старший Модератор
31795
6196
12.02.2009, 23:42
общий
Да, и если можно без GOTO

Смотрите в моих ответах, там точно есть и сложение прямого и дополнительного кода.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
12.02.2009, 23:45
общий
Спасибо Константин, только в "Моих ответах" это где? 1 раз на сайте.
Неизвестный
12.02.2009, 23:49
общий
Не вижу там, да и много очень. Не вариант кинуть текст программы? Без оператора GOTO...
Неизвестный
13.02.2009, 07:51
общий
gotoXY нужен только для нормального ввода с возможностью удаления цифр. Можно упростить ввод:
function InputBinary: String;
var buf: String; ch: char;
begin
Write('Введите бинарную строку: ');
buf := '';
repeat
ch := ReadKey;
case ch of
'0','1': begin buf := buf + ch; Write(ch) end;
end;
until (ch = #13) or (ch = #27) or (length(buf) >= 16); {ENTER или Esc или введенная строка равна 16 символам}
WriteLn;
if buf = '' then buf := '0';
InputBinary := buf
end;
давно
Старший Модератор
31795
6196
13.02.2009, 11:21
общий
Челпанников Алексей Алексеевич:

№160065, к примеру.
Выполняет А = А - В + С;
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
14.02.2009, 09:02
общий
WriteLn(num1,#10#13,'-',#10#13,num2,#10#13,'-------------');
Ошибка, не верное выражение.((((((((((((((((((((((((((((
Неизвестный
14.02.2009, 11:54
общий
Нет, верное, уверяю Вас, но в Borland Pascal или во FreePascal, то есть в НОРМАЛЬНЫХ.
И чуть повыше этого сообщения я дал вариант без этих символов.
В нормальном консольном приложении #13 - это символ с кодом 13 - управляющий символ "перевод в начало строки", #10 - это символ с кодом 10 = "перевод на следующую строку"
Мягкотвердые и тут помудрили : консолеподобное окно таковым не является
Неизвестный
14.02.2009, 13:50
общий
давно
Старший Модератор
31795
6196
16.02.2009, 10:44
общий
Челпанников Алексей Алексеевич:

Замените #10#13 на chr(10),chr(13)

вот за это(и ещё несколько других приколов) я и нелюблю АВС.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
16.02.2009, 11:11
общий
О, супер... да. Только Константин, она дает на ввод числа в 2 СС, а мне надо 16 СС((((((((((((((((( Что поменять чтобы она работала с ней?
давно
Старший Модератор
31795
6196
16.02.2009, 12:02
общий
это ответ
Здравствуйте, Челпанников Алексей Алексеевич!

Программа работающая в 16-ой СС(ввод-вывод), в приложении.
По функциям:
HexToBin рекурсивная функция преобразовывающая число в 16-ой системе в двоичную запись.
inputHex подпрограмма вводит число в 16-ой системе и возвращающая число в двоичной, запись двоичного числа производится в обратном порядке, с помощью этого достигается выравнивание чисел, т.е. разряды с одинаковым весом имеют одинаковые позиции в строке.
outputHex рекурсивная процедура выводит число в 16-ой системе. При рекурсии каждый раз обрабатывается одна 16-я цифра.
doSummaBin процедура суммирования двух двоичных чисел.
rangeBin процедура выравнивает введенные числа на размер определенный в разделе констант.
convertBin процедура перевода двоичного числа в дополнительный код.
Рабочимы числами в программе есть двоичные, а ввод и вывод производится в 16-ой системе, практически как и в самом процессоре.
Удачи!

Приложение:
uses crt;
const
n=32;
type
TMass=string[n];
var a,b,c:TMass;
function HexToBin(d,e:integer):string;
begin
{корректируем под 16-е число}
dec(d,7*ord(d>9));
HexToBin:='';
{рекурсивно формируем 16-е число ввиде двоичной строки}
if e>0 then HexToBin:=chr(ord('0') + d mod 2) + HexToBin(d div 2,e-1);
end;
procedure inputHex(var d:TMass;e:char);
begin{inputHex}
{вводим число в обратном порядке}
write('Enter number',e:2,':');
d:='';
repeat
e:=ReadKey;{символ без эхо}
case e of
'0'..'9','A'..'F','a'..'f':
begin
e:=chr(ord(e) - 32*ord(e>'Z'));{приводим число к единому регистру}
write(e);{выводим его}
d:=HexToBin(ord(e)-ord('0'),4)+d;{формируем двоичную строку}
end;
end;{case}
until (e=chr(13))or(length(d)=n);{}
writeln;
end;{inputHex}
procedure outputHex(d:TMass);
var
i:integer;
e:string;
begin{outputHex}
if length(d)>0 then
begin{if}
e:=copy(d,1,4);{получаем четыре бита}
delete(d,1,4);{удаляем их их числа}
outputHex(d);{рекурсивно вызываем себя}
i:=0;
while length(e)>0 do{преобразовываем строку в число}
begin{while}
i:=i*2 + ord(e[length(e)]) - ord('0');
delete(e,length(e),1);
end;{while}
inc(i,7*ord(i>9));{корректируем его с учетом 16-ой системы}
e:=chr(ord('0')+i);{формируем символ и выводим его}
write(e);
end;{if}
end;{outputHex}
procedure doSummaBin(var d,e:Tmass);
var
f:char;
i:integer;
begin{doSummaBin}
f:='0';{флаг переноса для старшего разряда}
for i:=1 to length(d) do
begin{for}
if (e[i]<>d[i])then
{обрабатываем ситуацию когда биты различны}
begin{ed=10,01}
if f='1'
then d[i]:='0' {edf=101,011}
else d[i]:='1';{edf=100,010}
end{10,01}
else
{обрабатываем ситуацию когда биты одинаковы}
begin{ed=00,11}
{edf=001,000,111,110}
d[i]:=f;
f:=e[i];
end;{00,11}
end;{for}
end;{doSummaBin}
procedure rangeBin(var d:Tmass);
begin{rangeBin}
while length(d)<n do
d:=d+'0';{}
end;{rangeBin}
procedure convertBin(var d:TMass;e:TMass);
var
i:integer;
begin{convertBin}
for i:=1 to length(d)do
{инвертируем биты}
case d[i]of{case}
'0':d[i]:='1';
'1':d[i]:='0';
end;{case}
rangeBin(e);{выравниваем строку}
doSummaBin(d,e);{суммируем}
end;{convertBin}
begin{main}
{вводим числа}
inputHex(a,'A');
inputHex(b,'B');
{выравниваем к одному размеру}
rangeBin(a);
rangeBin(b);
{переводим в дополнительный код}
convertBin(b,'1');
{суммируем А + Вд}
doSummaBin(a,b);
{выводим результат}
outputHex(a);
ReadKey;
end.{main}
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
16.02.2009, 12:35
общий
Ниже код исправленный под АВС:
Код:
  uses crt;
const
n=32;
type
TMass=string[n];
var a,b,c:TMass;
function HexToBin(d,e:integer):string;
begin
{корректируем под 16-е число}
{ dec(d,7*ord(d>9));}
if d>9 then dec(d,7);
HexToBin:='';
{рекурсивно формируем 16-е число ввиде строки}
if e>0 then HexToBin:=chr(ord('0') + d mod 2) + HexToBin(d div 2,e-1);
end;
procedure inputHex(var d:TMass;e:char);
begin{inputHex}
{вводим число в обратном порядке}
write('Enter number',e:2,':');
d:='';
repeat
e:=ReadKey;{символ без эхо}
case e of
'0'..'9','A'..'F','a'..'f':
begin
{ e:=chr(ord(e) - 32*ord(e>'Z'));{приводим число к единому регистру}
if e>'Z'then e:=chr(ord(e) - 32);
write(e);{выводим его}
d:=HexToBin(ord(e)-ord('0'),4)+d;{формируем двоичную строку}
end;
end;{case}
until (e=chr(13))or(length(d)=n);{}
writeln;
end;{inputHex}
procedure outputHex(d:TMass);
var
i,j:integer;
e:TMass;
begin{outputHex}
if length(d)>0 then
begin{if}
e:=copy(d,1,4);{получаем четыре бита}
{ delete(d,1,4);{удаляем их их числа}
outputHex(copy(d,5,length(d)-4));{рекурсивно вызываем себя}
i:=0;
j:=length(e);
while j>0 do{преобразовываем строку в число}
begin{while}
i:=i*2 + ord(e[j]) - ord('0');
dec(j);
end;{while}
if i>9 then inc(i,7);{*ord(i>9));{корректируем его с учетом 16-ой системы}
e:=chr(ord('0')+i);{формируем символ и выводим его}
write(e);
end;{if}
end;{outputHex}
procedure doSummaBin(var d,e:Tmass);
var
f:char;
i:integer;
begin{doSummaBin}
f:='0';{флаг переноса для старшего разряда}
for i:=1 to length(d) do
begin{for}
if (e[i]<>d[i])then
{обрабатываем ситуацию когда биты различны}
begin{ed=10,01}
if f='1'
then d[i]:='0' {edf=101,011}
else d[i]:='1';{edf=100,010}
end{10,01}
else
{обрабатываем ситуацию когда биты одинаковы}
begin{ed=00,11}
{edf=001,000,111,110}
d[i]:=f;
f:=e[i];
end;{00,11}
end;{for}
end;{doSummaBin}
procedure rangeBin(var d:Tmass);
begin{rangeBin}
while length(d)<n do
d:=d+'0';{}
end;{rangeBin}
procedure convertBin(var d:TMass;e:TMass);
var
i:integer;
begin{convertBin}
for i:=1 to length(d)do
{инвертируем биты}
case d[i]of{case}
'0':d[i]:='1';
'1':d[i]:='0';
end;{case}
rangeBin(e);{выравниваем строку}
doSummaBin(d,e);{суммируем}
end;{convertBin}
begin{main}
{вводим числа}
inputHex(a,'A');
inputHex(b,'B');
{выравниваем к одному размеру}
rangeBin(a);
rangeBin(b);
{переводим в дополнительный код}
convertBin(b,'1');
{суммируем А + Вд}
doSummaBin(a,b);
{выводим результат}
outputHex(a);
ReadKey;
end.{main}

Как видете функция ord не работает с перечисляемым типом, а должна(см. хелп паскаля):
Код:
 Булевы типы
Имеются четыре предопределенных булевых типа:Boolean, WordBool, LongBool и ByteBool.
Синтаксис:
Type Boolean = (False, True);
WordBool = (False, True);
LongBool = (False, True);
ByteBool = (False, True);
Замечания:
Эти типы имеют следующие размеры:
- Boolean - Byte (8 бит)
- WordBool - Word (16 бит)
- LongBool - LongInt (32 бита)
- ByteBool - Byte (8 бит)
Поскольку данные типы являются перечислимыми порядковыми типами, то существуют следующие связи:
False < True
Ord(False) = 0
Ord(True) = 1
Succ(False) = True
Pred(True) = False
Тип Boolean является предпочтительным, так как он использует наименьшее количество памяти.
ByteBool, WordBool и LongBool существуют только для совместимости с Windows.
В выражениях, следующие операторы сравнения производят результат типа Boolean:
= <> > < >= <= IN
Для совместимости с Windows, булевы типы могут принимать порядковые значения не только 0 и 1.
Булево выражение является ложью (False), если его порядковое значение равно нулю и истиной (True), если его порядковое значение не равно нулю.
Булевы операторы Not, And, Or и Xor работают проверяя значения на 0 (False) или не 0 (True), но всегда возвращают результат с порядковым значением 0 или 1.

Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа