« Ýðóäèöèÿ » Ðîññèéñêàÿ ýëåêòðîííàÿ áèáëèîòåêà

"Длинна�" арифметика

"Äëèííàÿ" àðèôìåòèêà

Èçâåñòíî, ÷òî àðèôìåòè÷åñêèå äåéñòâèÿ, âûïîëíÿåìûå êîìïüþòåðîì â îãðàíè÷åííîì ÷èñëå ðàçðÿäîâ, íå âñåãäà ïîçâîëÿþò ïîëó÷èòü òî÷íûé ðåçóëüòàò. Áîëåå òîãî, ìû îãðàíè÷åíû ðàçìåðîì (âåëè÷èíîé) ÷èñåë, ñ êîòîðûìè ìîæåì ðàáîòàòü. À åñëè íàì íåîáõîäèìî âûïîëíèòü àðèôìåòè÷åñêèå äåéñòâèÿ íàä î÷åíü áîëüøèìè ÷èñëàìè, íàïðèìåð,

30! = 265252859812191058636308480000000?

 òàêèõ ñëó÷àÿõ ìû ñàìè äîëæíû ïîçàáîòèòüñÿ î ïðåäñòàâëåíèè ÷èñåë â ìàøèíå è î òî÷íîì âûïîëíåíèè àðèôìåòè÷åñêèõ îïåðàöèé íàä íèìè.

×èñëà, äëÿ ïðåäñòàâëåíèÿ êîòîðûõ â ñòàíäàðòíûõ êîìïüþòåðíûõ òèïàõ äàííûõ íå õâàòàåò êîëè÷åñòâà äâîè÷íûõ ðàçðÿäîâ, íàçûâàþòñÿ "äëèííûìè". Ðåàëèçàöèÿ àðèôìåòè÷åñêèõ îïåðàöèé íàä òàêèìè "äëèííûìè" ÷èñëàìè ïîëó÷èëà íàçâàíèå "äëèííîé àðèôìåòèêè".

Îðãàíèçàöèÿ ðàáîòû ñ "äëèííûìè" ÷èñëàìè âî ìíîãîì çàâèñèò îò òîãî, êàê ìû ïðåäñòàâèì â êîìïüþòåðå ýòè ÷èñëà. "Äëèííîå" ÷èñëî ìîæíî çàïèñàòü, íàïðèìåð, ñ ïîìîùüþ ìàññèâà äåñÿòè÷íûõ öèôð, êîëè÷åñòâî ýëåìåíòîâ â òàêîì ìàññèâå ðàâíî êîëè÷åñòâó çíà÷àùèõ öèôð â "äëèííîì" ÷èñëå. Íî åñëè ìû áóäåì ðåàëèçîâûâàòü àðèôìåòè÷åñêèå îïåðàöèè íàä ýòèì ÷èñëîì, òî ðàçìåð ìàññèâà äîëæåí áûòü äîñòàòî÷íûì, ÷òîáû ðàçìåñòèòü â íåì è ðåçóëüòàò, íàïðèìåð, óìíîæåíèÿ.

Ñóùåñòâóþò è äðóãèå ïðåäñòàâëåíèÿ "äëèííûõ" ÷èñåë. Ðàññìîòðèì îäíî èç íèõ. Ïðåäñòàâèì íàøå ÷èñëî

30! = 265252859812191058636308480000000

â âèäå:

30! = 2 * (104)8 + 6525 * (104)7 + 2859 * (104) + 8121 * (104)5 + 9105 * (104)4 + 8636 * (104)3 + 3084 * (104)2 + 8000 * (104)1 + 0000 * (104)0.

Ýòî ïðåäñòàâëåíèå íàòàëêèâàåò íà ìûñëü î ìàññèâå, ïðåäñòàâëåííîì â òàáë. 1.

Òàáëèöà 1

Íîìåð ýëåìåíòà â ìàññèâå À

0

1

2

3

4

5

6

7

8

9

Çíà÷åíèå

9

0

8000

3084

8636

9105

8121

2859

6525

2

Ìû ìîæåì ñ÷èòàòü, ÷òî íàøå "äëèííîå" ÷èñëî ïðåäñòàâëåíî â 10000-10 ñèñòåìå ñ÷èñëåíèÿ (äåñÿòèòûñÿ÷íî-äåñÿòè÷íàÿ ñèñòåìà ñ÷èñëåíèÿ, ïðèâåäèòå àíàëîãèþ ñ âîñüìåðè÷íî-äåñÿòè÷íîé ñèñòåìîé ñ÷èñëåíèÿ), à "öèôðàìè" ÷èñëà ÿâëÿþòñÿ ÷åòûðåõçíà÷íûå ÷èñëà.

Âîçíèêàþò âîïðîñû. ×òî çà 9 â À [0], ïî÷åìó ÷èñëî õðàíèòñÿ "çàäîì íàïåðåä"? Îòâåòû î÷åâèäíû, íî ïîäîæäåì ñ ïðåæäåâðåìåííûìè îáúÿñíåíèÿìè. Îòâåòû íà âîïðîñû áóäóò ÿñíû èç òåêñòà.

Ïðèìå÷àíèå. Ìû ðàáîòàåì ñ ïîëîæèòåëüíûìè ÷èñëàìè!

Ïåðâàÿ çàäà÷à. Ââåñòè "äëèííîå" ÷èñëî èç ôàéëà. Ðåøåíèå çàäà÷è íà÷íåì ñ îïèñàíèÿ äàííûõ.

Const             MaxDig = 1000; {Ìàêñèìàëüíîå êîëè÷åñòâî öèôð — ÷åòûðåõçíà÷íûõ!}

   Osn = 10000; {Îñíîâàíèå íàøåé ñèñòåìû ñ÷èñëåíèÿ,

                           â ýëåìåíòàõ ìàññèâà õðàíèì ÷åòûðåõçíà÷íûå ÷èñëà}

Type             Tlong = Array[0..MaxDig] Of Integer;

   {Ìàêñèìàëüíîå êîëè÷åñòâî äåñÿòè÷íûõ öèôð â íàøåì ÷èñëå}

Àëãîðèòì ââîäà "äëèííîãî" ÷èñëà èç ôàéëà ðàññìîòðèì íà êîíêðåòíîì ïðèìåðå.

Ïóñòü â ôàéëå çàïèñàíî ÷èñëî 23851674 è îñíîâàíèåì (Osn) ÿâëÿåòñÿ 1000 (õðàíèì ïî òðè öèôðû â ýëåìåíòå ìàññèâà À). Èçìåíåíèå çíà÷åíèé ýëåìåíòîâ ìàññèâà À â ïðîöåññå ââîäà (ïîñèìâîëüíîãî â ïåðåìåííóþ Ch) îòðàæåíî â òàáë. 2.

Òàáëèöà 2

À[0]

À[1]

À[2]

À[3]

Ch

Ïðèìå÷àíèå

3

674

851

23

-

Êîíå÷íîå ñîñòîÿíèå

0

0

0

0

2

Íà÷àëüíîå ñîñòîÿíèå

1

2

0

0

3

1-é øàã

1

23

0

0

8

2-é øàã

1

238

0

0

5

3-é øàã

2

385

2

0

1

4-é øàã: ñòàðøàÿ öèôðà ýëåìåíòà À [1] ïåðåøëà â ïîêà "ïóñòîé" ýëåìåíò À[2]

2

851

23

0

6

5-é øàã

2

516

238

0

7

6-é øàã

3

167

385

2

4

7-é øàã

3

674

851

23

Ïðîàíàëèçèðóåì òàáëèöó (è ïîëó÷èì îòâåòû íà ïîñòàâëåííûå âûøå âîïðîñû).

1.  À[0] õðàíèì êîëè÷åñòâî çàäåéñòâîâàííûõ (íåíóëåâûõ) ýëåìåíòîâ ìàññèâà À — ýòî óæå î÷åâèäíî.

2. Ïðè îáðàáîòêå êàæäîé î÷åðåäíîé öèôðû âõîäíîãî ÷èñëà ñòàðøàÿ öèôðà ýëåìåíòà ìàññèâà ñ íîìåðîì i ñòàíîâèòñÿ ìëàäøåé öèôðîé ÷èñëà â ýëåìåíòå i+1, à ââîäèìàÿ öèôðà áóäåò ìëàäøåé öèôðîé ÷èñëà èç À[1].  ðåçóëüòàòå ðàáîòû íàøåãî àëãîðèòìà ìû ïîëó÷èëè ÷èñëî, çàïèñàííîå "çàäîì íàïåðåä".

Ïðèìå÷àíèå (ìåòîäè÷åñêîå): Ìîæíî îãðàíè÷èòüñÿ ýòèì îáúÿñíåíèåì è ðàçðàáîòêó ïðîöåäóðû âûíåñòè íà ñàìîñòîÿòåëüíîå çàäàíèå. Ìîæíî ïðîäîëæèòü îáúÿñíåíèå. Íàïðèìåð, âûïèñàòü ôðàãìåíò òåêñòà ïðîöåäóðû ïåðåíîñ ñòàðøåé öèôðû èç A[i] â ìëàäøóþ öèôðó À[i+1], ò.å. ñäâèã óæå ââåäåííîé ÷àñòè ÷èñëà íà îäíó ïîçèöèþ âïðàâî:

   For i := A[0] DownTo 1 Do

   Begin

               A[i+l] := A[i+l] + (Longint(A[i]) * 10) Div Osn;

               A[i] := (LongInt(A[i]) * 10) Mod Osn;

   End;

Ïóñòü ìû ââîäèì ÷èñëî 23851674 è ïåðâûå 6 öèôð óæå ðàçìåñòèëè "çàäîì íàïåðåä" â ìàññèâå À.  ñèìâîëüíóþ ïåðåìåííóþ ñ÷èòàëè î÷åðåäíóþ öèôðó "äëèííîãî" ÷èñëà — ýòî "7". Ïî íàøåìó àëãîðèòìó ýòà öèôðà "7" äîëæíà áûòü ðàçìåùåíà ìëàäøåé öèôðîé â À[1]. Âûïèñàííûé ôðàãìåíò ïðîãðàììû "îñâîáîæäàåò" ìåñòî äëÿ ýòîé öèôðû.  òàáëèöå îòðàæåíû ðåçóëüòàòû ðàáîòû ýòîãî ôðàãìåíòà.

i

À[1]

À[2]

À[3]

ch

2

516

238

0

7

2

516

380

2

1

160

385

2

Ïîñëå ýòîãî îñòàåòñÿ òîëüêî äîáàâèòü òåêóùóþ (ñ÷èòàííóþ â ch) öèôðó "äëèííîãî" ÷èñëà ê À[1] è èçìåíèòü çíà÷åíèå À[0].

 êîíå÷íîì èòîãå ïðîöåäóðà äîëæíà èìåòü ñëåäóþùèé âèä:

   Procedure ReadLong(Var A : Tlong);

   Var ch : char; i : Integer;

   Begin

               FillChar(A, SizeOf(A), 0) ;

               Read(ch);

               While Not(ch In ['0'..'9']) Do Read(ch);

               {ïðîïóñê íå öèôð âî âõîäíîì ôàéëå}

               While ch In ['0'..'9'] Do

               Begin

                           For i := A[0] DownTo 1 Do

                           Begin

                                       {"ïðîòàñêèâàíèå" ñòàðøåé öèôðû â ÷èñëå èç A[i]

                                       â ìëàäøóþ öèôðó ÷èñëà èç A[i+l]}

                                       A[i+l] := A[i+l] + (LongInt(A[i]) * 10) Div Osn;

                                       A[i] := (LongInt(A[i]) * 10) Mod Osn

                           End;

                           A[1] := A[l] + Ord(ch) - Ord('0');

                           {äîáàâëÿåì ìëàäøóþ öèôðó ê ÷èñëó èç À[1]}

                           If A[A[0]+1] > 0 Then Inc(A[0]);

                           {èçìåíÿåì äëèíó, ÷èñëî çàäåéñòâîâàííûõ ýëåìåíòîâ ìàññèâà À}

                           Read(ch)

               End

   End;

Âòîðàÿ çàäà÷à. Âûâîä "äëèííîãî" ÷èñëà â ôàéë èëè íà ýêðàí.

Êàçàëîñü áû, íåò ïðîáëåì — âûâîäè ÷èñëî çà ÷èñëîì. Îäíàêî â ñèëó âûáðàííîãî íàìè ïðåäñòàâëåíèÿ "äëèííîãî" ÷èñëà ìû äîëæíû âñåãäà ïîìíèòü, ÷òî â êàæäîì ýëåìåíòå ìàññèâà õðàíèòñÿ íå ïîñëåäîâàòåëüíîñòü öèôð "äëèííîãî" ÷èñëà, à çíà÷åíèå ÷èñëà, çàïèñàííîãî ýòèìè öèôðàìè. Ïóñòü â ýëåìåíòàõ ìàññèâà õðàíÿòñÿ ÷åòûðåõçíà÷íûå ÷èñëà. Òîãäà "äëèííîå" ÷èñëî 128400583274 áóäåò â ìàññèâå À ïðåäñòàâëåíî ñëåäóþùèì îáðàçîì:

A[0]

A[1]

A[2]

A[3]

3

3274

58

1284

Ïðè âûâîäå "äëèííîãî" ÷èñëà èç ìàññèâà íàì íåîáõîäèìî âûâåñòè 0058, èíà÷å áóäåò ïîòåðÿ öèôð. Èòàê, íåçíà÷àùèå íóëè òàêæå íåîáõîäèìî âûâîäèòü. Ïðîöåäóðà âûâîäà èìååò âèä:

   Procedure WriteLong(Const A : Tlong);

   Var             ls, s : String; i : Integer;

   Begin

               Str(Osn Div 10, Is);

               Write(A[A[0]]; {âûâîäèì ñòàðøèå öèôðû ÷èñëà}

               For i := A[0] - l DownTo 1 Do

               Begin

                           Str(A[i], s);

                           While Length(s) < Length(Is) Do s := '0' + s;

                           {äîïîëíÿåì íåçíà÷àùèìè íóëÿìè}

                           Write(s)

               End;

               WriteLn

   End;

Òðåòüÿ çàäà÷à. Ïðåäâàðèòåëüíàÿ ðàáîòà ïî îïèñàíèþ ñïîñîáà õðàíåíèÿ, ââîäó è âûâîäó "äëèííûõ" ÷èñåë âûïîëíåíà.

Ó íàñ åñòü âñå íåîáõîäèìûå "êèðïè÷èêè", íàïðèìåð, äëÿ íàïèñàíèÿ ïðîãðàììû ñëîæåíèÿ äâóõ "äëèííûõ" ïîëîæèòåëüíûõ ÷èñåë. Èñõîäíûå ÷èñëà è ðåçóëüòàò õðàíèì â ôàéëàõ. Íàçîâåì ïðîöåäóðó ñëîæåíèÿ SumLongTwo.

Òîãäà ïðîãðàììà ââîäà äâóõ "äëèííûõ" ÷èñåë è âûâîäà ðåçóëüòàòà èõ ñëîæåíèÿ áóäåò èìåòü ñëåäóþùèé âèä:

   Var A, B, C : Tlong;

   Begin

               Assign(Input, 'Input.txt'); Reset(Input);

               ReadLong(A); ReadLong(B) ;

               Close(Input);

               SumLongTwo(A, B, C);

               Assign(Output, 'Output.txt');

               Rewrite(Output);

               WriteLong(C);

               Close(Output)

   End.

Àëãîðèòì ïðîöåäóðû ñëîæåíèÿ ìîæíî îáúÿñíèòü íà ïðîñòîì ïðèìåðå. Ïóñòü À=870613029451, Â=3475912100517461.

i

A[i]

B[i]

C[1]

C[2]

C[3]

C[4]

1

9451

7461

6912

1

0

0

2

1302

51

6912

1354

0

0

3

8706

9121

6912

1354

7827

1

4

0

3475

6912

1354

7827

3476

Àëãîðèòì èìèòèðóåò ïðèâû÷íîå ñëîæåíèå ñòîëáèêîì, íà÷èíàÿ ñ ìëàäøèõ ðàçðÿäîâ. È èìåííî äëÿ ïðîñòîòû ðåàëèçàöèè àðèôìåòè÷åñêèõ îïåðàöèé íàä "äëèííûìè" ÷èñëàìè èñïîëüçóåòñÿ ìàøèííîå ïðåäñòàâëåíèå "çàäîì íàïåðåä".

Ðåçóëüòàò: Ñ = 3476782713546912.

Íèæå ïðèâåäåí òåêñò ïðîöåäóðû ñëîæåíèÿ äâóõ "äëèííûõ" ÷èñåë.

   Procedure SumLongTwo(A, B : Nlong; Var C : Tlong);

   Var i, k : Integer;

   Begin

               FillChar(C, SizeOf (C), 0) ;

               If A[0] > B[0] Then k := A[0] Else k : =B[0];

               For i := l To k Do

               Begin             Ñ [i+1] := (C[i] + A[i] + B[i]) Div Osn;

                           C[i] := (C[i] + A[i] + B[i]) Mod Osn

                           {Åñòü ëè â ýòèõ îïåðàòîðàõ îøèáêà?}

               End;

               If C[k+l] = 0 Then C[0] := k Else C[0] := k + l

   End;

×åòâåðòàÿ çàäà÷à. Ðåàëèçàöèÿ îïåðàöèé ñðàâíåíèÿ äëÿ "äëèííûõ" ÷èñåë (À=Â, À<Â, À>Â, À<=Â, À>=Â).

   Function Eq(A, B : TLong) : Boolean;

   Var i : Integer;

   Begin

               Eq := False;

               If A[0] <> B[0] Then Exit

               Else Begin

                           i := l;

                           While (i <= A[0]) And (A[i] = B[i]) Do Inc(i);

                           Eq := i = A[0] + l

                     End

   End;

Ðåàëèçàöèÿ ôóíêöèè À >  òàêæå ïðîçðà÷íà.

   Function More(A, B : Tlong) : Boolean;

   Var i : Integer;

   Begin If A[0] < B[0]             Then More := False

                                       Else             If A[0] > B[0] Then More := True

                                                   Else Begin

                                                               i := A[0];

                                                               While (i > 0) And (A[i] = B[i]) Do Dec(i);

                                                               If i = 0             Then More := False

                                                                           Else If A[i] > B[i] Then More := True

                                                               Else More:=False

                                                   End

   End;

Îñòàëüíûå ôóíêöèè ðåàëèçóþòñÿ ÷åðåç ôóíêöèè Eq è More.

   Function Less(A, B : Tlong) : Boolean; {A < B}

   Begin

               Less := Not(More(A, B) Or Eq(A, B))

   End;

   Function More_Eq(A, B : Tlong) : Boolean; {A >= B}

   Begin

               More_Eq := More(A, B) Or Eq(A, B)

   End;

   Function Less_Eq(A, B : Tlong) : Boolean; {A <= B}

   Begin

               Less_Eq := Not More(A, B)

   End;

Äëÿ ñàìîñòîÿòåëüíîãî ðåøåíèÿ ìîæåò áûòü ïðåäëîæåíà ñëåäóþùàÿ, áîëåå ñëîæíàÿ, çàäà÷à. Òðåáóåòñÿ ðàçðàáîòàòü ôóíêöèþ, êîòîðàÿ âûäàåò 0, åñëè À áîëüøå Â, 1, åñëè À ìåíüøå Â, è 2 ïðè ðàâåíñòâå ÷èñåë. Íî ñðàâíåíèå äîëæíî áûòü âûïîëíåíî ñ ó÷åòîì ñäâèãà. Î ÷åì èäåò ðå÷ü? Ïîÿñíèì íà ïðèìåðå. Ïóñòü À ðàâíî 56784, à  — 634. Ïðè ñäâèãå ÷èñëà  íà 2 ïîçèöèè âëåâî ôóíêöèÿ äîëæíà ñêàçàòü, ÷òî  áîëüøå À, áåç ñäâèãà, ÷òî À áîëüøå Â. Äðóãîé ïðèìåð. Ïðè À ðàâíîì 56700, à  — 567 è ñäâèãå 2 ôóíêöèÿ äîëæíà "ñêàçàòü", ÷òî ÷èñëà ðàâíû. Ðåøåíèå ìîæåò èìåòü ñëåäóþùèé âèä:

Function More(Const À, Â : Tlong; Const sdvig : Integer) : Byte;

Var i : Integer;

Begin

   If A[0] > B[0] + sdvig Then More := 0

                                       Else

                                                   If A[0] < B[0] + sdvig Then More := l

                                                   Else Begin

                                                               i := A[0];

                                                               While (i > sdvig) And

                                                                           (A[i] = B[i-sdvig]) Do Dec(i);

                                                               If i = sdvig Then Begin

                                                                                       More:=0;

                                                               {ñîâïàäåíèå ÷èñåë ñ ó÷åòîì ñäâèãà}

                                                                                       For i := 1 To sdvig Do

                                                                                                   If A[i] > 0 Then Exit;

                                                                                       More := 2;

                                                               {÷èñëà ðàâíû, "õâîñò" ÷èñëà À ðàâåí íóëþ}

                                                                                       End

                                                               Else More := Byte(A[i] < B[i-sdvig])

                                                   End

End;

Ïÿòàÿ çàäà÷à. Óìíîæåíèå äëèííîãî ÷èñëà íà êîðîòêîå. Ïîä êîðîòêèì ïîíèìàåòñÿ öåëîå ÷èñëî òèïà LongInt.

Ïðîöåäóðà î÷åíü ïîõîäèò íà ïðîöåäóðó ñëîæåíèÿ äâóõ äëèííûõ ÷èñåë.

   Procedure Mul(Const A : TLong; Const Ê : Longlnt; Var Ñ : TLong);

   Var i : Integer;

   {ðåçóëüòàò - çíà÷åíèå ïåðåìåííîé Ñ}

   Begin

               FillChar (Ñ, SizeOf(Ñ), 0);

               If K = 0 Then Inc(Ñ[0]){óìíîæåíèå íà íîëü}

               Else Begin

                           For i:= l To A[0] Do

                           Begin

                                       C[i+l] := (LongInt(A[i]) * K + C[i]) Div Osn;

                                       C[i] := (LongInt(A[i])* K + C[i]) Mod Osn

                           End;

                           If C[A[0]+1] > 0 Then C[0]:= A[0] + 1

                           Else C[0]:= A[0]

                           {îïðåäåëÿåì äëèíó ðåçóëüòàòà}

                           End

   End;

Øåñòàÿ çàäà÷à. Âû÷èòàíèå äâóõ äëèííûõ ÷èñåë ñ ó÷åòîì ñäâèãà

Åñëè ïîíÿòèå ñäâèãà ïîêà íå ïîíÿòíî, òî îñòàâüòå åãî â ïîêîå, íà ñàìîì äåëå âû÷èòàíèå ñ ó÷åòîì ñäâèãà ïîòðåáóåòñÿ ïðè ðåàëèçàöèè îïåðàöèè äåëåíèÿ.  íà÷àëå âûÿñíèòå ëîãèêó ðàáîòû ïðîöåäóðû ïðè íóëåâîì ñäâèãå.

Ââåäåì îãðàíè÷åíèå: ÷èñëî, èç êîòîðîãî âû÷èòàþò, áîëüøå ÷èñëà, êîòîðîå âû÷èòàåòñÿ. Ðàáîòàòü ñ "äëèííûìè" îòðèöàòåëüíûìè ÷èñëàìè ìû íå óìååì.

Ïðîöåäóðà áûëà áû ïîõîæà íà ïðîöåäóðû ñëîæåíèÿ è óìíîæåíèÿ, åñëè áû íå îäíî "íî" — çàèìñòâîâàíèå åäèíèöû èç ñòàðøåãî ðàçðÿäà âìåñòî ïåðåíîñà åäèíèöû â ñòàðøèé ðàçðÿä. Íàïðèìåð, â îáû÷íîé ñèñòåìå ñ÷èñëåíèÿ ìû âû÷èòàåì 9 èç 11 — èäåò çàèìñòâîâàíèå 1 èç ðàçðÿäà äåñÿòêîâ, à åñëè èç 10000 âû÷èòàåì 9 — ïðîöåññ çàèìñòâîâàíèÿ íåñêîëüêî ñëîæíåå.

   Procedure Sub (Var A : TLong; Const B : TLong; Const sp : Integer);

   Var i, j : Integer;

               {èç À âû÷èòàåì  ñ ó÷åòîì ñäâèãà sp, ðåçóëüòàò âû÷èòàíèÿ â À}

   Begin

               For i := l To B[0] Do

               Begin Dec(A[i+sp], B[i]);

                           j: = i;{*}

                           {ðåàëèçàöèÿ ñëîæíîãî çàèìñòâîâàíèÿ}

                           while (A[j+sp] < 0) and (j <= A[0]) Do

                           Begin{*}

                                       Inc(A[j+sp], Osn) ;

                                       Dec(A[j+sp+l]); Inc(j); {*}

                           end; {*}

                           {Ðåàëèçàöèÿ ïðîñòîãî çàèìñòâîâàíèÿ.

                           Åñëè îïåðàòîðû, îòìå÷åííûå *, çàìåíèòü

                           íà íèæåïðèâåäåííûå îïåðàòîðû â ôèãóðíûõ ñêîáêàõ, òî,

                           ïî ïîíÿòíûì ïðè÷èíàì, ëîãèêà íå áóäåò ðàáîòàòü

                           ïðè âñåõ èñõîäíûõ äàííûõ. Ìîæíî ñîçíàòåëüíî ñäåëàòü

                           îøèáêó è ïðåäëîæèòü íàéòè åå — ïðèíöèï "îáó÷åíèå ÷åðåç îøèáêó"}

                           {If A[i+sp]<0 Then Begin Inc(A[i+sp], Osn);

                           Dec (A[i+sp+l]);End;}

               End;

               i := A[0];

               While (i > l) And (A[i] = 0) Do Dec(i);

               A[0] := i

               {êîððåêòèðîâêà äëèíû ðåçóëüòàòà îïåðàöèè}

   End;

Ðåêîìåíäóåòñÿ âûïîëíèòü òðàññèðîâêó ðàáîòû äàííîé ïðîöåäóðû, íàïðèìåð, äëÿ ñëåäóþùèõ èñõîäíûõ äàííûõ. ×èñëî À ðàâíî 100000001000000000000, ÷èñëî  — 2000073859998.

Ñåäüìàÿ çàäà÷à. Äåëåíèå äâóõ äëèííûõ ÷èñåë, ò.å. íàõîæäåíèå öåëîé ÷àñòè ÷àñòíîãî è îñòàòêà.

Íàïèñàòü èñõîäíóþ (áåç óòî÷íåíèé) ÷àñòü ëîãèêè íå ñîñòàâëÿåò òðóäà. Ýòî:

   Procedure Long_Div_Long(Const À, Â : TLong; Var Res, Ost : TLong);

   Begin

               FillChar(Res, SizeOf(Res), 0); Res[0] := 1;

               FillChar(Ost, SizeOf(Ost), 0); 0st[0] := 1;

               Case More(A, B, 0) Of

               0: MakeDel(A, B, Res, Ost);

               {À áîëüøå Â, ïîêà íå çíàåì, êàê âûïîëíÿòü îïåðàöèþ - "âûíîñèì" â ïðîöåäóðó}

               1: Ost:=A; {À ìåíüøå Â}

               2: Res[l] := l; {À ðàâíî Â}

               End;

   End;

À äàëüøå? Äàëüøå íà÷èíàþòñÿ ïðîáëåìû. Äåëèòü ñòîëáèêîì íàñ íàó÷èëè â øêîëå. Íàïðèìåð,

      1000143123567 |73859998

     - 73859998     |----------

       ---------    |13541 (Öåëàÿ ÷àñòü ÷àñòíîãî)

       261543143

     - 221579994

       ----------

        399631495

      - 369299990

         ---------

         303315056

       - 295439992

         ----------

           78750647

         - 73859998

           --------

            4890649 (Îñòàòîê)

×òî ìû äåëàëè? Íà êàæäîì ýòàïå â óìå ïîäáèðàëè öèôðó (1, 3, 5 è ò.ä.), òàêóþ, ÷òî ïðîèçâåäåíèå ýòîé öèôðû íà äåëèòåëü äàåò ÷èñëî ìåíüøåå, íî íàèáîëåå áëèçêîå ê ÷èñëó... Êàêîìó? Ýòî òðóäíî ñêàçàòü ñëîâàìè, íî èç ïðèìåðà ÿñíî. Çà÷åì íàì ýòî äåëàòü â óìå, ïóñòü äåëàåò êîìïüþòåð. Îäíàêî óïðîñòèì ïðèìåð, îñòàâèì åãî äëÿ òåñòèðîâàíèÿ îêîí÷àòåëüíîé ëîãèêè ïðîöåäóðû, òåì áîëåå ÷òî è ÷èñëà "äëèííûå". Ïóñòü ÷èñëî À áóäåò ìåíüøå Â*10, òîãäà â ðåçóëüòàòå (öåëîé ÷àñòè äåëåíèÿ) áóäåò îäíà öèôðà. Íàïðèìåð, À ðàâíî 564, à  — 63 è ïðîñòàÿ äåñÿòè÷íàÿ ñèñòåìà ñ÷èñëåíèÿ. Ïîïðîáóåì ïîäîáðàòü öèôðó ðåçóëüòàòà, íî íå ìåòîäîì ïðÿìîãî ïåðåáîðà, à ìåòîäîì äåëåíèÿ îòðåçêà ïîïîëàì. Ïóñòü Down — âåðõíÿÿ ãðàíèöà èíòåðâàëà èçìåíåíèÿ ïîäáèðàåìîé öèôðû, Up — íèæíÿÿ ãðàíèöà èíòåðâàëà, Ost ðàâåí äåëèìîìó.

Down

Up

Ñ = Â * ( (Down + Up) Div 2)

Ost = 564

0

10

315 = 63 * ( (0 + 10) Div 2)

C < Ost

5

10

441 = 63 * ( (5 + 10) Div 2)

C < Ost

7

10

504 = 63 * ( (7 + 10) Div 2)

C < Ost

8

10

567 = 63 * ( (8 + 10) Div 2)

C > Ost

8

9

504 = 63 * ( (8 + 9) Div 2)

C < Ost

Èòàê, ðåçóëüòàò — öåëàÿ ÷àñòü ÷àñòíîãî — ðàâåí (Up + Down) Div 2, îñòàòîê îò äåëåíèÿ — ðàçíîñòü ìåæäó çíà÷åíèÿìè Ost è Ñ. Íèæíþþ ãðàíèöó (Down) èçìåíÿåì, åñëè ðåçóëüòàò (Ñ) ìåíüøå îñòàòêà, âåðõíþþ (Up), — åñëè áîëüøå.

Óñëîæíèì ïðèìåð. Ïóñòü À ðàâíî 27856, à  — 354. Îñíîâàíèåì ñèñòåìû ñ÷èñëåíèÿ ÿâëÿåòñÿ íå 10, à 10000.

Down

Up

Ñ

Ost = 27856

0

10000

1770000

C > Ost

0

5000

885000

C > Ost

0

2500

442500

C > Ost

0

1250

221250

C > Ost

0

625

110448

C > Ost

0

312

55224

C > Ost

0

156

27612

C < Ost

78

156

41418

C > Ost

78

117

34338

C > Ost

78

97

30798

C > Ost

78

87

29028

C > Ost

78

82

28320

C > Ost

78

80

27966

C > Ost

78

79

27612

C < Ost

Öåëàÿ ÷àñòü ÷àñòíîãî ðàâíà 78, îñòàòîê îò äåëåíèÿ — 27856 ìèíóñ 27612, ò.å. 244.

Ïîðà ïðèâîäèòü ïðîöåäóðó. Èñïîëüçóåìûå "êèðïè÷èêè": ôóíêöèÿ ñðàâíåíèÿ ÷èñåë (More) ñ ó÷åòîì ñäâèãà è ôóíêöèÿ óìíîæåíèÿ äëèííîãî ÷èñëà íà êîðîòêîå (Mul) îïèñàíû âûøå.

Function FindBin(Var Ost : Tlong; Const  : TLong; Const sp : Integer) : Longint;

Var Down, Up : Word; C : TLong;

Begin

   Down := 0;Up := 0sn;

   {îñíîâàíèå ñèñòåìû ñ÷èñëåíèÿ}

   While Up - l > Down Do

   Begin

               {Åñòü âîçìîæíîñòü ïðåïîäàâàòåëþ ñäåëàòü

               ñîçíàòåëüíóþ îøèáêó. Èçìåíèòü óñëîâèå

               öèêëà íà Up>Down. Ðåçóëüòàò - çàöèêëèâàíèå ïðîãðàììû.}

               Mul(Â, (Up + Down) Div 2, Ñ);

               Case More(Ost, C, sp) Of

               0: Down := (Down + Up) Div 2;

               1: Up := (Up + Down) Div 2;

               2: Begin Up := (Up + Down) Div 2; Down := Up End;

               End;

   End;

   Mul(B, (Up + Down) Div 2, C);

   If More (Ost, C, 0) = 0 Then Sub(Ost, C, sp)

               {íàõîäèì îñòàòîê îò äåëåíèÿ}

   Else begin Sub (C, Ost, sp); Ost := C end;

   FindBin := (Up + Down) Div 2;

   {öåëàÿ ÷àñòü ÷àñòíîãî}

End;

Îñòàëîñü ðàçîáðàòüñÿ ñî ñäâèãîì, çíà÷åíèåì ïåðåìåííîé sp â íàøåì èçëîæåíèè. Îïÿòü âåðíåìñÿ ê îáû÷íîé ñèñòåìå ñ÷èñëåíèÿ è ïîïûòàåìñÿ ðàçäåëèòü, íàïðèìåð, 635 íà 15. ×òî ìû äåëàåì? Âíà÷àëå äåëèì 63 íà 15 è ôîðìèðóåì, ïîäáèðàåì â óìå ïåðâóþ öèôðó ðåçóëüòàòà. Ïîäáèðàòü ñ ïîìîùüþ êîìïüþòåðà ìû íàó÷èëèñü. Ïîäîáðàëè — ýòî öèôðà 4, è ýòî ñòàðøàÿ öèôðà ðåçóëüòàòà. Èçìåíèì îñòàòîê. Åñëè âíà÷àëå îí áûë 635, òî ñåé÷àñ ñòàë 35. Âû÷èòàòü ñ ó÷åòîì ñäâèãà ìû óìååì. Îïÿòü ïîäáèðàåì öèôðó. Âòîðóþ öèôðó ðåçóëüòàòà. Ýòî öèôðà 2 è îñòàòîê 5. Èòàê, ðåçóëüòàò (öåëàÿ ÷àñòü) 42, îñòàòîê îò äåëåíèÿ 5. À ÷òî èçìåíèòñÿ, åñëè îñíîâàíèåì áóäåò íå 10, à 10000? Ëîãèêà ñîâïàäàåò, òîëüêî â óìå ñ÷èòàòü íåñêîëüêî òðóäíåå, íî âåäü ó íàñ æå åñòü ìîëîòîê ïîä íàçâàíèåì êîìïüþòåð — ïóñòü îí âáèâàåò ãâîçäè.

Procedure MakeDel(Const À, Â : TLong; Var Res, Ost : TLong);

Var sp : Integer;

Begin

   Ost := A; {ïåðâîíà÷àëüíîå çíà÷åíèå îñòàòêà}

   sp := À[0] - Â[0];

   If More(À, Â, sp) = l Then Dec(sp);

   {B * Osn > A, â ðåçóëüòàòå îäíà öèôðà}

   Res[0] := sp + l;

   While sp >= 0 Do

   Begin

               {íàõîäèì î÷åðåäíóþ öèôðó ðåçóëüòàòà}

               Res[sp + 1] := FindBin(Ost, B, sp);

               Dec(sp)

   End

End;

Ìåòîäè÷åñêèå ðåêîìåíäàöèè. Ïðåäñòàâëåííûé ìàòåðèàë èçëàãàåòñÿ íà ÷åòûðåõ çàíÿòèÿõ ïî èçâåñòíîé ñõåìå: 10-15-ìèíóòíîå èçëîæåíèå èäåé, à çàòåì ðàáîòà ó÷àùèõñÿ ïîä ðóêîâîäñòâîì ïðåïîäàâàòåëÿ.

1-å çàíÿòèå. Ââîä, âûâîä è ñëîæåíèå äëèííûõ ÷èñåë (çàäà÷è 1, 2, 3).

2-å çàíÿòèå. Ôóíêöèè ñðàâíåíèÿ (çàäà÷à 4).

3-å çàíÿòèå. Óìíîæåíèå è âû÷èòàíèå äëèííûõ ÷èñåë (çàäà÷è 5, 6).

4-å çàíÿòèå. Äåëåíèå äëèííûõ ÷èñåë (çàäà÷à 7). Áåçóñëîâíî, ýòà ñõåìà íå äîãìà.  çàâèñèìîñòè îò óðîâíÿ ïîäãîòîâêè ó÷àùèõñÿ íà ñàìîñòîÿòåëüíîå âûïîëíåíèå ìîæåò áûòü âûíåñåíà çíà÷èòåëüíàÿ ÷àñòü ìàòåðèàëà. Çàìå÷ó òîëüêî, ÷òî â ñèëó ñëîæèâøåéñÿ òðàäèöèè â ðÿäå ñëó÷àåâ äîïóñêàþòñÿ ïðè èçëîæåíèè ñîçíàòåëüíûå îøèáêè.  ðåçóëüòàòå ðàáîòû êàæäûé ó÷àùèéñÿ äîëæåí èìåòü ñîáñòâåííûé ìîäóëü äëÿ ðàáîòû ñ "äëèííûìè" ÷èñëàìè.

Òåìû äëÿ èññëåäîâàíèé

1. Ðåøåíèå çàäà÷: ïîèñê íàèáîëüøåãî îáùåãî äåëèòåëÿ äâóõ "äëèííûõ" ÷èñåë; ïîèñê íàèìåíüøåãî îáùåãî êðàòíîãî äâóõ "äëèííûõ" ÷èñåë; èçâëå÷åíèå êâàäðàòíîãî êîðíÿ èç "äëèííîãî" ÷èñëà è ò.ä.

2. "Äëèííûå" ÷èñëà ìîãóò áûòü îòðèöàòåëüíûìè. Êàê èçìåíÿòñÿ îïèñàííûå âûøå îïåðàöèè äëÿ ýòîãî ñëó÷àÿ?

3. Äëÿ õðàíåíèÿ "äëèííûõ" ÷èñåë èñïîëüçóåòñÿ íå ìàññèâ, à ñòåê, ðåàëèçîâàííûé ñ ïîìîùüþ ñïèñêà. Ìîäèôèöèðîâàòü ìîäóëü ðàáîòû ñ "äëèííûìè" ÷èñëàìè.

Ñïèñîê ëèòåðàòóðû

Ñ.Ì. Îêóëîâ/ "Äëèííàÿ" àðèôìåòèêà/

Äëÿ ïîäãîòîâêè äàííîé ðàáîòû áûëè èñïîëüçîâàíû ìàòåðèàëû ñ ñàéòà http://www.comp-science.narod.ru/


Íåïðàâèëüíàÿ êîäèðîâêà â òåêñòå?
 ðàáîòå íå äîñòàåò êàêèõ ëèáî êàðòèíîê?
Äîêóìåíò îòôîðìàòèðîâàí íåêîððåêòíî?

Âû ìîæåòå ñêà÷àòü ïðàâèëüíî îòôîðìàòèðîâàííóþ ðàáîòó
Ñêà÷àòü ðåôåðàò