2023(e)ko martxoaren 27(a), astelehena

10. astea | Errusiar Biderketaren Metodoa programatzen

Errusiar Biderketaren Metodoa izenburuko artikulua gogoratuz, ariketa honetan bi zenbakiren arteko biderkadura kalkulatzen duen programa egingo dugu, baina biderketa burutzeko taulak arrayetan gordez.









TAULAREN NEURRIA ETA DATU-MOTA


Jakinik biderkagai biak integer datu-motakoak direla (biak 0 eta MAXINT artekoak), biderkadura longint datu-motakoa izango da. Gogora ekar dezagun 4. astea | Errusiar Biderketaren Metodoa programatzen artikulua eta bertan ematen den ErrusiarBiderketarenMetodoaProgramatzen.pas kodea, programa hori exekutatzean biderkagai handienak sartuko bagenitu ondoko emaitza eskuratuko genuke:






Horregatik, taularen datu-mota holako zerbait izango da, non zutabeak bi diren eta errenkaden kopurua iLUZERA oraindik ez dugun zehaztu:



1
2
3
type
   taliTaula = array[0..iLUZERA, 1..2] of longint ;


Errenkaden behemuga 0 izatea komeniko zaigu eta errenkaden goimuga den iLUZERA zehazteko jakin behar dugu "erdiak ematen dituen sekuentzia" segida logaritmiko bat dela, lehen biderkagaiaren baliorik handiena aukeratuko bagenu iBiderkagai1 = MAXINT = 32767 mailak 14 izango lirateke:




2rMailak = iBiderkagai1 = 32767


log2(2rMailak) = log2(32767)

rMailak·log2(2) = log2(32767)

rMailak = log2(32767)/log2(2)

rMailak = ln(32767)/ln(2) = 14.99995

iMailak = 14



Mailak 14 izango dira gehienez, baina biderkagai biak taulak bildu nahi ditugunez, errenkaden behemuga 0 izan dadila eta errenkada horretan datuak diren biderkagai biak kokatuko ditugu. Ondorioz, taularen datu-mota hau izango da:



1
2
3
4
5
6
7
8
9
10
11
program ErrusiarBiderketarenMetodoa_ARRAY ;
 
const
   iLUZERA = 14 ;
                                             
type
   taliTaula = array[0..iLUZERA, 1..2] of longint ;   (* errenkaden kopuru maximoa: iLUZERA *)
                                                      (* biderkagai biak 0. errenkadan      *)
                                                      (* zutaben kopurua beti: 2            *)
   ...                                                   








TAULAREN JAKIN BATEN NEURRI EFEKTIBOA


Jakinik biderkagai biak integer datu-motakoak direla (biak 0 eta MAXINT artekoak), biderkadura longint datu-motakoa izango da eta, gehienez, taularen neurria 15x2 izango da (0 errenkada barne). Baina, exekuzio jakin batean ez da zertan taula osoa bete behar; adibidez, biderkagaiak 34 eta 7 badira taularen neurri efektiboa honako ha izango da:



                                  Erdiak   Dobleak
------ -------
0. maila 34 7
1. maila 17 14
2. maila 8 28
3. maila 4 56
4. maila 2 112
5. maila 1 224


Argi dago zutabeak beti 2 izango direla eta taularen neurri efektikoa errenkada baliagarriak kopuruak finkatuko duela (goiko adibidean 5).








ADIBIDE BAT



Laburbilduz: Aurreko azpiataleko goiko taula hori memorian gordetzeko, bi dimentsiotako array bat beharko dugu, hots, zenbaki osoen taula bat beharko dugu. Orokorrean, bi dimentsiotako arrayaren indizeak 0-tik 14-ra joango dira errenkadetan eta zutabeak izendatzeko 1 eta 2 indizeak erabiliko ditugu. Baina adibidera etorriz, taularen neurria 5x2 izango da (non 2 beti konstantea den), horregatik iLuzeraEfek aldagaian 5 gordeko da.




iBiderkagai1 aldagaian 34 hartu bada, eta iBiderkagai2 aldagaian 7 hartu bada, aliTaula arrayaren itxura honako hau izango da, non iMailak = iLuzeraEfek = 5 izango den:






































































aliTaula
       1  
   2   
0     34       7   
1    17  
   14   
2     8       28   
3     4       56   
4     2      112   
5 1 224
6    
7    
...    
13    
14    




Errusiar Biderketaren Metodoa aplikatuz, lehen zutabeko bikoitien errenkadak kenduko ditugu eta  aliTaula arraya abiapuntuz harturik aliTaulaLaburra arraya eskuratuko dugu:






































































aliTaula
       1  
   2   
0    34       7   
1    17  
   14   
2     8       28   
3     4       56   
4     2      112   
5 1 224
6    
7    
...    
13    
14    




aliTaulaLaburra array berriaren itxura honako hau izango da, non adibide honetan errenkadak bi direlako iLuzeraEfek = 1 izango den:


















































aliTaulaLaburra
       1  
   2   
0    17  
   14   
1     1     224 
2    
3    
...    
13    
14    




Eskumako zutabean geratu diren zenbakien batuketa eginez, lortu den 14+224=238 batura bilatzen dugun emaitza da, hots, lortutako batura helburuko 34x7=238 biderkadura bezalakoa da.








PROGRAMAREN ITURBURU-KODEA


Arrayak darabilen Errusiar Biderketaren Metodoaren programa bat jarraian erakusten da:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
{ "Errusiar Biderketaren Metodoa" aplikatzen duen programa bat idatzi nahi da.   }
 
{ DATUAK:                                                                        }
{       Sarrerako datuak bi biderkagaiak izango dira, biak positiboak eta osoak. }
{ EMAITZA:                                                                       }
{       Irteera biderkadura izango da, bere datu-mota LONGINT izango da.         }
 
{ Arrayaren neurria zehazteko, suposatuko dugu sarrerako biderkagairik handiena  }
{ MAXINT izango dela. Horregatik:     2^rLUZERA = MAXINT                         }
{                                     rLUZERA·ln(2) = ln(MAXINT)  >>>  rLUZERA   }
{                                     rLUZERA = ln(MAXINT) / ln(2) = 14.99995    }
{                                     iLUZERA = trunc(ln(MAXINT) / ln(2) = 14    }
 
program ErrusiarBiderketarenMetodoa_ARRAY ;
 
const
   iLUZERA = 14 ;
   HANDIENA = MAXINT ;     (* MAXINT bada daturik garaiena iLUZERA 14 izan beharko da *)
                                             
type
   taliTaula = array[0..iLUZERA, 1..2] of longint ;   (* errenkaden kopuru maximoa: iLUZERA *)
                                                      (* biderkagai biak 0. errenkadan      *)
                                                      (* zutaben kopurua beti: 2            *)
    
 
function ifnZenbakiarenMailakKalkulatu(iZenbakia: integer): integer ;  
var
   rMailak: real ;
   iMailak: integer ;
begin
   //writeln('Adibidea -->  2^X=63 ekuazioaren ebazpena 5,98 da eta mailak 5 dira.') ;
   //writeln('Adibidea -->  2^X=64 ekuazioaren ebazpena 6,00 da eta mailak 6 dira.') ;
   //writeln('Adibidea -->  2^X=65 ekuazioaren ebazpena 6,02 da eta mailak 6 dira.') ;    
                                           (* 2^x = 65         *)
   rMailak := ln(iZenbakia) / ln(2) ;      (* x·ln(2) = ln(65) *)
   iMailak := trunc(rMailak) ;
 
   //writeln(iOINARRIA:15, '^X=', iZenbakia, ' ekuazioaren ebazpena ', rMailak:0:2, ' da. Mailak ', iMailak, ' dira.') ;
    
   ifnZenbakiarenMailakKalkulatu := iMailak ;
end ;  
    
 
procedure TaulaBete(var aliTaula: taliTaula;
                     iLuzeraEfek: integer;
                      iZenbaki_1: integer;
                      iZenbaki_2: integer) ;  
var
   iErrenkada: integer ;
   liErdia, liDoblea: LongInt ;  
begin   
   aliTaula[0, 1] := iZenbaki_1 ;
   aliTaula[0, 2] := iZenbaki_2 ;
       
   liErdia := iZenbaki_1 ;
   liDoblea := iZenbaki_2 ;
   for iErrenkada:=1 to iLuzeraEfek do
   begin
      liErdia := liErdia div 2 ;
      liDoblea := liDoblea * 2 ;
      aliTaula[iErrenkada, 1] := liErdia ;
      aliTaula[iErrenkada, 2] := liDoblea ;
   end ;    
end ;
 
    
procedure TaulaIkusi(const aliTaula: taliTaula;
                        iLuzeraEfek: integer) ;  
var
   iErrenkada: integer ;
begin 
   writeln('Erdiak':32, 'Dobleak':15) ;
   writeln('------':32, '-------':15) ;
   for iErrenkada:=0 to iLuzeraEfek do
   begin
      write(iErrenkada:10, '. maila') ;
      write(aliTaula[iErrenkada, 1]:15) ;
      writeln(aliTaula[iErrenkada, 2]:15) ;
   end ;
end ;    
 
 
procedure ErrenkadaBikoitiakKendu(     const aliTaula: taliTaula;
                                          iLuzeraEfek: integer;
                                  var aliTaulaLaburra: taliTaula;
                                   var iLuzeraLaburra: integer) ;
var
   iErrenkada: integer ;
begin
   iLuzeraLaburra := -1 ;     (* taularen lehen errenkada 0 delako *)
   for iErrenkada:=0 to iLuzeraEfek do
   begin
      if aliTaula[iErrenkada, 1] mod 2 = 1 then
      begin
         iLuzeraLaburra := iLuzeraLaburra + 1 ;
         aliTaulaLaburra[iLuzeraLaburra, 1] := aliTaula[iErrenkada, 1] ;
         aliTaulaLaburra[iLuzeraLaburra, 2] := aliTaula[iErrenkada, 2] ;
      end ;
   end ;
end ;                                   
                                       
  
function fnliBatuketakEgin(const aliTaulaLaburra: taliTaula;
                                  iLuzeraLaburra: integer): longint ;
var
   iErrenkada: integer ;
   liBatura: longint ;
begin
   liBatura := 0 ;
   for iErrenkada:=0 to iLuzeraLaburra do
   begin
      liBatura := liBatura + aliTaulaLaburra[iErrenkada, 2] ;
      //writeln(iErrenkada, '. batura = ', liBatura:0:2) ;
   end ;
    
   fnliBatuketakEgin := liBatura ;
end ;  
 
{ ----------------------------------------------------------------------------- }
     
var
   iZenbaki_1, iZenbaki_2, iMailak, iLuzeraEfek, iLuzeraLaburra: integer ;
   aliTaula, aliTaulaLaburra: taliTaula ; 
   liBiderkadura: longint
begin
   writeln ;
   writeln('MAXINT ----> ', MAXINT) ;
   writeln('iLUZERA = trunc(ln(MAXINT) / ln(2)) ----> ', trunc(ln(MAXINT) / ln(2))) ;
   writeln ;
   writeln ;
    
   writeln(' -------------------------------') ;
   writeln('| Errusiar Biderketaren Metodoa =============') ;
   writeln('| -----------------------------              |') ;
   writeln('|                                            |') ;
   writeln('| Kopuru positiboekin lan eginez, bi zenbaki |') ;
   writeln('| irakurri eta haien biderkadura kalkulatu.  |') ;
   writeln(' ============================================') ;
   writeln ;
    
   repeat
      write('   Lehen biderkagaia eman (1 eta ', HANDIENA, ' artekoa), 39 adibidez: ') ;
      readln(iZenbaki_1) ;
   until (iZenbaki_1 > 0) and (iZenbaki_1 <= HANDIENA) ;
    
   repeat
      write('Bigarren biderkagaia eman (0 eta ', HANDIENA, ' artekoa),  7 adibidez: ') ;
      readln(iZenbaki_2) ;
   until (iZenbaki_2 >= 0) and (iZenbaki_2 <= HANDIENA) ;     
    
   iMailak := ifnZenbakiarenMailakKalkulatu(iZenbaki_1) ;
    
   writeln ;
   writeln(iZenbaki_1, ' biderkagaiari dagokion maila kopurua ', iMailak, ' da:') ;
    
   iLuzeraEfek := iMailak ;
    
   TaulaBete(aliTaula, iLuzeraEfek, iZenbaki_1, iZenbaki_2) ;   (* taularen bigarren dimentsioa ez da behar beti 2 delako *)  
    
   writeln ;
   TaulaIkusi(aliTaula, iLuzeraEfek) ;   (* taularen bigarren dimentsioa ez da behar beti 2 delako *)
   writeln ;
 
   ErrenkadaBikoitiakKendu(aliTaula, iLuzeraEfek, aliTaulaLaburra, iLuzeraLaburra) ;
    
   TaulaIkusi(aliTaulaLaburra, iLuzeraLaburra) ;   (* taularen bigarren dimentsioa ez da behar beti 2 delako *)
   writeln ;
    
   liBiderkadura := fnliBatuketakEgin(aliTaulaLaburra, iLuzeraLaburra) ; 
  
   writeln('"Errusiar Biderketaren Metodoa" aplikatuz:    ', iZenbaki_1, ' x ', iZenbaki_2, ' = ', liBiderkadura) ; 
   writeln('Biderkadura ohiko * operadorearen bitartez:   ', iZenbaki_1, ' * ', iZenbaki_2, ' = ', iZenbaki_1 * iZenbaki_2) ;     
 
   writeln ;
   writeln('====================================================') ;
   writeln('             RETURN sakatu amaitzeko') ;
   writeln('====================================================') ;
   readln ;
end.



 

iruzkinik ez:

Argitaratu iruzkina