Реферат: Операции многократной точности (операции с длинными числами)
<span Times New Roman",«serif»">ЗаданиеОперациимногократной точности (т.е. операции с длинными числами).
<span Times New Roman",«serif»">Конкретизация заданияСначалабуквам присваивается значение – например: а=23850934, причем все переменные –целые числа, которые по длине не должны превышать 300 знаков. Потом пишется выражение, например f=(a+b)/c+(d+a). При этомделение – это целое от деления делимого на делитель. Операции сложения,вычитания, умножения – обычные арифметические операции, только это операции наддлинными числами. Кроме сложения, вычитания, умножения и деления еще могут бытьиспользованы скобки.
<span Times New Roman",«serif»">Формат вводаЛюбую строку в поле ввода можно представить в видеS={C,V}
Где S– константа либо вычисляемое значение. Если это –константа, то С – число в строковом виде, перед которым стоит символ «@», а еслиSнадо найти то S=V, где V– выражение с переменными и числами. В строке недолжно быть пробелов и все переменные состоят из одой буквы. Между строками вполе ввода не должно быть пустых строк. Вывод идет аналогично вводу. Примерввода и вывода можно посмотреть на рисунке
<span Times New Roman",«serif»">Интерфейс программы.Интерфейс программы – ее внешнийвид является наглядным и удобным. В верхнем поле ввода пишутся известныевеличины и формулы, потом жмется кнопка «Расчитать» и в нижнем поле выводятся валфавитном порядке все переменные. Программа написана в среде программирования Delphi6. Использовались только стандартные компоненты – TEditи TButton. Итого наформе размещено поле ввода, поле вывода и кнопка – для запуска процессарасчета. Использование визуаль <img src="/cache/referats/13709/image002.jpg" v:shapes="_x0000_s1027">
ныхсредств разработки на много ускорило процесс написания программы.
Все длинныечисла представляются в виде строки, каждый элемент которой – цифра. Если числоотрицательное, то первым символом строки будет “-“. Чтобы считать по формулеиспользуем структуру, описанную ниже
type
dd= record
lin:array[1..300] of string;
dl:integer;
end;
var
mas:array[1..300] of dd;
В массиве masхранится уравнение. Каждый элемент массива –отдельное уравнение. В linхранятсяотдельные элементы уравнения. Например mas[3].lin=(‘A’,’=’,’3’,’/’,’(‘,’B’,’-‘,’1’,’)’) соответствует уравнению A=3/(B-1). В первом элементе (mas[i].lin[1]) всегдахранится буква, во втором (mas[i].lin[2]) символ “=”. Такая форма ведения уравнения нужна для удобства вычисления длинныхформул. В dlхранитсятекущее число элементов в уравнении+1. Можно сказать – если dl=4, то в данном элементе хранится не формула, которуюнадо вычислить, а значение.
Количествострок введенных в поле ввода должно быть не более 300 – это задается размерностьюмассива mas.
<span Times New Roman",«serif»">Используемые процедуры и функцииzapolnenie; — заполнение массива masиз поля edt1.
sum(a,b:string):string; — сумма чисел, хранящихся в aи b.
minus(a,b:string):string; — разностьчисел, хранящихсявa иb. minus=a-b
umn(a:integer;var xx:string):string;- умножениечислаххнацифруа. Используетсявфункцииumnozen.
umnozen(a,b:string):string; — произведение чисел, хранящихся в aи b.
del2(str:string):string; — делитчислоstr на2.
sravnenie(a,b:string):shortint; — сравнивает число aс числом b. Возвращается результат:
·<span Times New Roman"">
если а>b, то sravnenie=1·<span Times New Roman"">
если а<b, то sravnenie=-1·<span Times New Roman"">
если а<b, то sravnenie=0delen(a,b:string):string; — частное от деления aна b. Беретсяцелая часть.
po_ch_num(ch:string;varznach:string):boolean; — ищетзначение буквы в массиве mas. Еслизначение найдено то возвращается значение «Истина», в противном случае «Ложь».Функция используется для подстановки чисел в выражения. Аргументы: ch– буква, значение которой мы ищем, znach– найденное значение.
sislo(ch:char):boolean; — проверяет – является ли символ chцифрой. Если да – то возвращается «Истина». Функцияиспользуется для определения константа или выражения соответствует заданнойбукве.
poisk(z:integer); — процедура для вычисления значения выражения. Она опирается на все предыдущиепроцедуры и функции. Z– номервычисляемого значения в массиве mas. Алгоритмее работы таков: считаем количество открывающихся скобок и если они есть, тоначинаем считать с самой вложенной, потом идет умножение и деление, потом суммаи разность. После каждой операции длина уравнения уменьшается и обращение идетопять к процедуре poiskс тем жепараметром z.
vivod; — вывод найденных значений в поле вывода memo3.
TForm1.Button1Click(Sender: TObject); — процедура нажатия на кнопку«Расчет».
TForm1.Button2Click(Sender: TObject); — процедура нажатия на кнопку«Задание».
Все функциииспользуют глобальную переменную masи всепроцедуры и функции между собой тесно связаны.
Рассмотрималгоритм работы процедуры umnozen
<span Times New Roman",«serif»; mso-fareast-font-family:«Times New Roman»;mso-ansi-language:RU;mso-fareast-language: RU;mso-bidi-language:AR-SA">Ввод a,b
Bol=false
b<0
a>=0
b=-b
bol=true
да
нет
a<0
b>=0
a=-a
bol=true
да
нет
<img src="/cache/referats/13709/image003.gif" v:shapes="_x0000_s1028 _x0000_s1029 _x0000_s1032 _x0000_s1033 _x0000_s1034 _x0000_s1036 _x0000_s1037 _x0000_s1038 _x0000_s1040 _x0000_s1042 _x0000_s1043 _x0000_s1044 _x0000_s1045 _x0000_s1046 _x0000_s1047 _x0000_s1048 _x0000_s1049 _x0000_s1050 _x0000_s1051">a<0
b<0
b=-b
a=-a
да
нет
a=0
b=0
да
нет
k=length(b)
c=0
tmp=’’
k>=1
да
r=umn(b[k],a)
r=r+tmp
tmp:=tmp+’0’
c=sum(c,r)
k=k-1
нет
bol=true
да
c=’-‘+c
нет
umnozen=c
Выход
<img src="/cache/referats/13709/image004.gif" v:shapes="_x0000_s1052 _x0000_s1053 _x0000_s1054 _x0000_s1055 _x0000_s1056 _x0000_s1057 _x0000_s1058 _x0000_s1059 _x0000_s1060 _x0000_s1067 _x0000_s1068 _x0000_s1069 _x0000_s1071 _x0000_s1072 _x0000_s1073 _x0000_s1074 _x0000_s1075 _x0000_s1076 _x0000_s1077 _x0000_s1078 _x0000_s1079 _x0000_s1081 _x0000_s1082 _x0000_s1083 _x0000_s1084 _x0000_s1085 _x0000_s1086 _x0000_s1087 _x0000_s1088 _x0000_s1089 _x0000_s1090 _x0000_s1091 _x0000_s1092 _x0000_s1093 _x0000_s1094 _x0000_s1095 _x0000_s1096 _x0000_s1097 _x0000_s1098 _x0000_s1099 _x0000_s1100 _x0000_s1101 _x0000_s1102"><span Times New Roman",«serif»">Листинг программы
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes,Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids;
type
dd= record
lin:array[1..300] of string;
dl:integer;
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Label1: TLabel;
Label3: TLabel;
Memo3: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
function minus(a,b:string):string;
function sum(a,b:string):string;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
mas:array[1..300] of dd;
vs1:integer;{elementov v zn}
y:integer; {elementov v mas}
implementation
{$R *.DFM}
procedurezapolnenie;
var
tmp:string;
j,nn,ll:integer;
chislo:boolean;
begin
y:=0;
for ll:=0 to form1.Memo1.Lines.Count do begin
tmp:=form1.Memo1.Lines[ll];
y:=y+1;
mas[y].dl:=1;
nn:=0;
chislo:=false;
tmp:=ansiuppercase(tmp);
for j:=1 to length(tmp) do begin
if tmp[1]='@' then begin
mas[y].lin[3]:=copy(tmp,4,300);
mas[y].lin[1]:=tmp[2];
mas[y].lin[2]:=tmp[3];
mas[y].dl:=4;
break;
end
else begin
mas[y].lin[mas[y].dl]:=copy(tmp,nn+1,j-nn);
mas[y].dl:=mas[y].dl+1;
nn:=j;
end;
end;
end;
end;
functionTForm1.sum(a,b:string):string;
var
tmp,c,tmp2:string;
i,k,ost,j:integer;
bol:boolean;
begin
if ((b[1]='-') and (a[1]<>'-')) thenbegin
sum:=form1.minus(a,copy(b,2,300)); exit;
end;
if ((a[1]='-') and (b[1]<>'-')) thenbegin
sum:=form1.minus(b,copy(a,2,300)); exit;
end;
bol:=false;
if ((b[1]='-') and (a[1]='-')) then begin
bol:=true; a:=copy(a,2,300);b:=copy(b,2,300)
end;
if length(b)>length(a) then begin
tmp:=b; b:=a; a:=tmp;
end;
ost:=0;
if length(b)<>length(a) then b:='0'+b;
c:=a;
j:=length(a);
tmp2:='';
for i:=length(b) downto 1 do begin
tmp2:=tmp2+'0';
k:=strtoint(c[j])+strtoint(b[i]);
k:=k+ost;
ost:=0;
if k>9 then begin
ost:=k div 10; k:=k mod 10;
end;
c[j]:=inttostr(k)[1];
j:=j-1;
end;
if ost>0 then begin
tmp2:=inttostr(ost)+tmp2;
c:=form1.sum(tmp2,c);
end;
if bol then c:='-'+c;
sum:=c;
end;
functionTform1.minus(a,b:string):string;
var
i,la,lb,vv,snos:integer;
c,tmp:string;
pom:boolean;
begin
if ((b[1]='-') and (a[1]<>'-')) thenbegin
minus:=form1.sum(a,copy(b,2,300)); exit;
end;
if ((a[1]='-') and (b[1]<>'-')) thenbegin
minus:=form1.sum(a,'-'+b); exit;
end;
if ((b[1]='-') and (a[1]='-')) then begin
minus:=form1.minus(copy(b,2,300),copy(a,2,300));exit;
end;
c:=a;
pom:=false;
la:=length(a); lb:=length(b);
if lb>la then begin
pom:=true; c:=b; b:=a; a:=c;
la:=length(a); lb:=length(b);
end;
snos:=0;
for i:=lb downto 1 do begin
vv:=strtoint(a[la-lb+i])-strtoint(b[i])-snos;
snos:=0;
if vv<0 then begin
snos:=1; vv:=vv+10;
end;
c[la-lb+i]:=inttostr(vv)[1];
end;
if snos=1 then begin
tmp:='';
for i:=1 to lb do tmp:=tmp+'0';
tmp:='1'+tmp;
c:=minus(c,tmp);
end;
while ((c[1]='0')and(length(c)>1)) doc:=copy(c,2,300);
if pom then c:='-'+c;
minus:=c;
end;
functionumn(a:integer;varxx:string):string;
var
i,ost,tmp,dl:integer;
str:string;
begin
ost:=0;
str:='';
dl:=length(xx);
for i:=dldownto 1 do begin
tmp:=a*strtoint(xx[i])+ost;
if tmp>9 then begin
str:=inttostr((tmp mod 10))+str;
ost:=tmp div 10;
if i=1 then str:=inttostr(ost)+str;
end
else begin
str:=inttostr(tmp)+str;
ost:=0;
end;
end;
umn:=str;
end;
functionumnozen(a,b:string):string;
var
k,i:integer;
tmp,c,r:string;
bol:boolean;
begin
bol:=false;
if ((b[1]='-') and (a[1]<>'-')) thenbegin
bol:=true; b:=copy(b,2,300);
end;
if ((a[1]='-') and (b[1]<>'-')) thenbegin
bol:=true; a:=copy(a,2,300);
end;
if ((b[1]='-') and (a[1]='-')) then begin
a:=copy(a,2,300); b:=copy(b,2,300)
end;
if ((a='0')or(b='0')) then begin
umnozen:='0'; exit;
end;
k:=length(b);
c:='0'; tmp:='';
for i:=k downto 1 do begin
r:=umn(strtoint(b[i]),a);
r:=r+tmp;
tmp:=tmp+'0';
c:=form1.sum(c,r);
end;
if bol then c:='-'+c;
umnozen:=c;
end;
functionsravnenie(a,b:string):shortint;
{ если а>b, то сравнение=1
если а<b, то сравнение=-1
если а<b, то сравнение=0}
var
la,lb,i:integer;
begin
la:=length(a); lb:=length(b);
if a[1]='-' then begin
if b[1]='-' then sravnenie:=sravnenie(b,a)
else sravnenie:=-1;
exit;
end;
if b[1]='-' then begin
if a[1]='-' then sravnenie:=sravnenie(b,a)
else sravnenie:=1;
exit;
end;
if lb>la then sravnenie:=-1;
if lb<la then sravnenie:=1;;
if la=lb then begin
for i:=1 to la do begin
if a[i]>b[i] then begin
sravnenie:=1;
exit;
end;
if a[i]<b[i] then begin
sravnenie:=-1;
exit;
end;
end;
sravnenie:=0;
end;
end;
functiondel2(str:string):string;
var
ost,i:integer;
dr:string;
begin
ost:=0;
dr:='';
for i:=1 to length(str) do begin
dr:=dr+inttostr((strtoint(str[i])+ost*10)div 2);
ost:=((strtoint(str[i])+ost*10) mod 2);
end;
if dr[1]='0' then dr:=copy(dr,2,300);
del2:=dr;
end;
functiondelen(a,b:string):string;
{delen=round(a/b)}
var
bol,zzz:boolean;
pr,tmp,lev,prav,rab:string;
begin
if b='0' then begin
showmessage('Íàíîëü äåëèòüíåëüçÿ!');
delen:='';
exit;
end;
zzz:=false;
if ((b[1]='-') and (a[1]<>'-')) thenbegin
zzz:=true; b:=copy(b,2,300);
end;
if ((a[1]='-') and (b[1]<>'-')) thenbegin
zzz:=true; a:=copy(a,2,300);
end;
if ((b[1]='-') and (a[1]='-')) then begin
a:=copy(a,2,300); b:=copy(b,2,300)
end;
bol:=true;
lev:='0'; prav:=a; pr:='0'; rab:=a;
if b<>'1' then
while (bol) do begin
tmp:=form1.minus(a,pr);
if tmp[1]='-' then tmp:=copy(tmp,2,300);
if (sravnenie(tmp,del2(b))<>1) thenbreak;//bol:=false;
tmp:=form1.minus(prav,lev); rab:='';
rab:=form1.sum(lev,del2(tmp));
pr:=umnozen(b,rab);
if sravnenie(a,pr)=1 then begin
lev:=rab;
end
else begin
prav:=rab;
end;
end;
if zzz then rab:='-'+rab;
delen:=rab;
if ((rab='-')or(rab=''))then delen:='0';
end;
functionpo_ch_num(ch:string;varznach:string):boolean;
var
bol:boolean;
i:integer;
begin
bol:=false;
for i:=1 to y do begin
if ((mas[i].dl=4)and(mas[i].lin[1]=ch))then begin
bol:=true;
znach:=mas[i].lin[3];
end;
end;
po_ch_num:=bol;
end;
functionsislo(ch:char):boolean;
begin
if ((ch>='0')and(ch<='9')or(ch='-'))then sislo:=true
else sislo:=false;
end;
procedurepoisk(z:integer);
var
i,k,j,m,k2,zz:integer;
tmp:string;
zn:char;
begin
{snachala ubiraem skobki, potom *, potom /,potom +, potom -}
k:=0;
for i:=1 to mas[z].dl-1 do
if mas[z].lin[i]='(' then k:=k+1;
if k>0 then begin
k2:=0;
for i:=1 to mas[z].dl-1 do begin
if mas[z].lin[i]='(' then k2:=k2+1;
if k2=k then begin
if mas[z].lin[i+2]=')' then begin
mas[z].lin[i]:=mas[z].lin[i+1];
for m:=i+1 to mas[z].dl-2 domas[z].lin[m]:=mas[z].lin[m+2];
mas[z].dl:=mas[z].dl-2;
poisk(z);
exit;
end
else begin
zz:=i+1;
while mas[z].lin[zz]<>')' dobegin
if((mas[z].lin[zz]='*')or(mas[z].lin[zz]='/')) then begin
ifpo_ch_num(mas[z].lin[zz-1],tmp) then mas[z].lin[zz-1]:=tmp;
ifpo_ch_num(mas[z].lin[zz+1],tmp) then mas[z].lin[zz+1]:=tmp;
if(((sislo(mas[z].lin[zz-1][1])))and(sislo(mas[z].lin[zz+1][1]))) then begin
zn:=mas[z].lin[zz][1];
if zn='*' thenmas[z].lin[zz-1]:=umnozen(mas[z].lin[zz-1],mas[z].lin[zz+1])
elsemas[z].lin[zz-1]:=delen(mas[z].lin[zz-1],mas[z].lin[zz+1]);
for m:=zz to mas[z].dl-2 domas[z].lin[m]:=mas[z].lin[m+2];
mas[z].dl:=mas[z].dl-2;
poisk(z);
exit;
end;
end;
zz:=zz+1;
end;
//////// {snachala / i *, potom + i -}
zz:=i+1;
while mas[z].lin[zz]<>')' dobegin
if((mas[z].lin[zz]='+')or(mas[z].lin[zz]='-')) then begin
ifpo_ch_num(mas[z].lin[zz-1],tmp) then mas[z].lin[zz-1]:=tmp;
ifpo_ch_num(mas[z].lin[zz+1],tmp) then mas[z].lin[zz+1]:=tmp;
if((sislo(mas[z].lin[zz-1][1]))and(sislo(mas[z].lin[zz+1][1]))) then begin
zn:=mas[z].lin[zz][1];
if zn='+' thenmas[z].lin[zz-1]:=form1.sum(mas[z].lin[zz-1],mas[z].lin[zz+1])
elsemas[z].lin[zz-1]:=form1.minus(mas[z].lin[zz-1],mas[z].lin[zz+1]);
for m:=zz to mas[z].dl-2 domas[z].lin[m]:=mas[z].lin[m+2];
mas[z].dl:=mas[z].dl-2;
poisk(z);
exit;
end;
end;
zz:=zz+1;
end;
////////
end;
end;
end;
end
else begin {esli skobok net}
for zz:=1 to mas[z].dl-1 do begin if((mas[z].lin[zz]='*')or(mas[z].lin[zz]='/')) then begin
ifpo_ch_num(mas[z].lin[zz-1],tmp) then mas[z].lin[zz-1]:=tmp;
ifpo_ch_num(mas[z].lin[zz+1],tmp) then mas[z].lin[zz+1]:=tmp;
if((sislo(mas[z].lin[zz-1][1]))and(sislo(mas[z].lin[zz+1][1]))) then begin
zn:=mas[z].lin[zz][1];
if zn='*' thenmas[z].lin[zz-1]:=umnozen(mas[z].lin[zz-1],mas[z].lin[zz+1])
elsemas[z].lin[zz-1]:=delen(mas[z].lin[zz-1],mas[z].lin[zz+1]);
for m:=zz to mas[z].dl-2 domas[z].lin[m]:=mas[z].lin[m+2];
mas[z].dl:=mas[z].dl-2;
poisk(z);
exit;
end;
end;
end;
for zz:=1 to mas[z].dl-1 do begin
////////
if ((mas[z].lin[zz]='+')or(mas[z].lin[zz]='-'))then begin
ifpo_ch_num(mas[z].lin[zz-1],tmp) then mas[z].lin[zz-1]:=tmp;
ifpo_ch_num(mas[z].lin[zz+1],tmp) then mas[z].lin[zz+1]:=tmp;
if((sislo(mas[z].lin[zz-1][1]))and(sislo(mas[z].lin[zz+1][1]))) then begin
zn:=mas[z].lin[zz][1];
if zn='+' thenmas[z].lin[zz-1]:=form1.sum(mas[z].lin[zz-1],mas[z].lin[zz+1])
elsemas[z].lin[zz-1]:=form1.minus(mas[z].lin[zz-1],mas[z].lin[zz+1]);
for m:=zz to mas[z].dl-2 domas[z].lin[m]:=mas[z].lin[m+2];
mas[z].dl:=mas[z].dl-2;
poisk(z);
exit;
end;
end;
///////
end;
end;
end;
procedurevivod;
var
i:integer;
begin
form1.Memo3.Clear;
for i:=1 to y do
if mas[i].dl=4 then begin
form1.Memo3.Lines.Add(mas[i].lin[1]+'='+mas[i].lin[3]);
end;
end;
procedureTForm1.Button1Click(Sender:TObject);
var
i,j:integer;
begin
zapolnenie;
for j:=1 to y do
for i:=1 to y do poisk(i);
vivod;
end;
procedureTForm1.Button2Click(Sender:TObject);
begin
messagedlg('Îïåðàöèèìíîãîêðàòíîéòî÷íîñòè',mtinformation,[mbok],0);
end;
end.