Hogyan lehet egy tetszőlegesen hosszú szám négyzetét kiszámolni?
Az összeadással és kivonással nem akadt nehézségem, a számokat stringként tárolva, majd számjegyenként, az általános iskolás írásbeli összeadás/kivonás algoritmusát felhasználva nem volt nehéz megvalósítani.
Viszont a négyzetre emelés (és a szorzás) az írásbeli szorzást leutánozva elég bonyolultnak tűnik. Nincs valami algoritmus egy szám négyzetének meghatározására?
Egy gondolat:
A szorzás visszavezethető összeadások sorozatára...
Pl.:
5*5 = 5+5+5+5+5
Egyszer kellett Big Number típust csinálnom egy egyetemi beadandóhoz, akkor a szorzást egy olyan algoritmussal oldottam meg, ami hátulról előre haladva kalkulálja ki az eredmény számjegyeit.
A lényeg az volt, hogy az eredmény helyiértéke egyenlő lesz a két összeszorzott számjegy helyiértékének összegénél eggyel kisebb számmal (plusz túlcsordulás, ha túllépi a szorzat a 10-et). ÍGy meg lehetett határozni, hogy mely számjegyek szorzatai fogják meghatározni az egyes, tizes, százas, stb, helyiértéket.
Pl az eredmény első helyiértéke a két szorzandó szám első helyiértékének szorzatából fog előállni. (1+1-1=1)
Az eredmény második helyiértéke a két összeszorzandó szám első és második (1+2-1=2), valamint második és első (2+1-1=2) helyiértékének szorzatából fog előállni.
A harmadiknál nyilván az 1-3, 2-2, és 3-1 helyiértékek szorzata lesz mérvadó, és így tovább (fontos, hogy sorban haladj, mert a túlcsordulás miatt az előző helyiértékben kiszámolt szorzat is átcsúszhat a következőre).
A vicces rész ott kezdődik, amikor a két szám nem egyforma hosszú, így az egyiknek hamarabb érsz a végére, mint a másiknak. FEl kell tehát készítenia programot arra, hogy ha az egyik számból már nem tudsz magasabb helyiértékre lépni, akkor a másik számot kell magasabb helyiértéken kezdeni. (pl az egyik szám 4 jegyű, a másik 7, Az eredmény szám 5. helyiértékének meghatározásánál a 7 jegyű számnak nem fogod tudni az első helyiértékét számításba venni, mivel a másikból a 4. helyiérték a legmagasabb (4+1-1=4)
Én ezt így oldottam meg, és működött a történet.
Szia.
Anno még Assemblerben kellet valami hasonlót összehoznom, de mivel én egyszerű ember vagyok a sima papiros szorzást programoztam le akkor, és Neked is ezt ezt javaslom.
Van a szám (ennek megvannak a számjegyei pl 100 darab számjegy).
Felveszel annyi stringet ahány számjegy van, a string hosszát kétszer akkorára veszed fel mint a számjegyek száma, ez 100 számjegy esetén 100 db 200 karakter hosszúságú stringet jelent, (ha a stringeket feltöltod valamilyen nem szám karakterrel akkor már egy kis előkészitést is végeztél).
Aztán egy ciklussal végigmész a a szorzó számjegyeket, elvégzed a számjegyek szorzását (figyelsz az átvitelekre, illetve arra is hogy a számjegynek megfelelően a string kezdetét elcsúsztatod annyi karakterrel ahányadik számjeggyel számolsz), és beleteszed a megfelelő stringbe (első számjegy az első stringben az első poziciótól kezdve, második számjegy szorzata a második stringbe a második poziciótól kezdve, stb,stb).
Ha kész utána két egymásba ágyazott ciklussal végigmész a stringeken (az egyik ciklus a stringek hosszáig(200), amíg másik ciklus a stringkek darabszámáig megy(100)), és az egymás felett lévő számokat összeadot (itt is figyelsz az átvitelre) illetve a nem szám karakterekre, egymás felett lévő számok alatt értem a string azonos poziciójában lévő számokat. Az eredményt letárolod egy stringben.
Meghatározod az eredmény string hosszát, és kiiratod.
Ha tört van a szorzásban akkor még a szabályoknak megfelelően a tizedes vessző helyét is meghatározod és belerakod az eredménybe.
Sok sikert.
üdv.
De amúgy ha igazán jó megoldást akarsz:
'Hátulról támadva' - értsd szorzás - Delphi-ben, kicsit bő lére eresztve:
program Project2;
{$APPTYPE CONSOLE}
uses SysUtils, Classes;
var a, b, s : String;
hossz, szorzo, szorzando, szorzat, osszeg, atvitel, hely, sor : Integer;
lista : TStringList;
begin
a := '12345678901234567890123456789012345678';
b := '32109876543210987654321012345678901234';
lista := TStringList.Create;
hossz := Length(a) + Length(b) + 3;
sor := 0;
for szorzo := Length(b) downto 1 do
begin
atvitel := 0;
hely := 0;
s := StringOfChar('0', hossz);
for szorzando := Length(a) downto 1 do
begin
szorzat := (Ord(a[szorzando]) - 48) * (Ord(b[szorzo]) - 48) + atvitel;
atvitel := szorzat div 10;
s[hossz - hely - sor] := Chr((szorzat mod 10) + 48);
Inc(hely);
end;
s[hossz - hely - sor] := Chr(atvitel + 48);
Inc(sor);
WriteLn(s);
lista.Add(s);
end;
s := StringOfChar('-', hossz);
WriteLn(s);
s := StringOfChar('0', hossz);
atvitel := 0;
for hely := hossz downto 1 do
begin
osszeg := 0;
for sor := 0 to lista.Count - 1 do osszeg := osszeg + (Ord(lista.Strings[sor][hely]) - 48);
osszeg := osszeg + atvitel;
atvitel := osszeg div 10;
s[hely] := Chr((osszeg mod 10) + 48);
end;
WriteLn(s);
while s[1] = '0' do Delete(s, 1, 1);
WriteLn(#10#13, 'Az "tiszta" eredmény: ',#10#13, s);
lista.Free;
ReadLn;
end.
Szia.
Volt egy kis időm, így én is leprogramoztam ezt a feladatot, menet közben átgondoltam a logikát és nem kell a string tömb, kb. két string elég az egészhez.
Az elmélet : Egy ciklusban szorzod az első számot a második szám megfelelő számjegyével. Aztán ezt a részeredményt összeadod az eredmény stringjével (Ez két függvény : SzorzasEgyJeggyel és Osszead).
A konzolról kéri be a számot (de csak egy ellenőrzés van benne: a tizedes vesszőt kicseréli tizedes pontra, ha van benne tizedes vessző)
Aztán kiírja az egyes részeredmények értékét. Majd a végeredményt is.
Kezeli a törteket is (legalább is kiszedi a tizedespontot a beadott adatokból és meghatározza a végeredmény tizedesjegyeinek számát, és alkalmazza is a végeredményen).
Itt a forrás (Delphi konzolos alkalmazás) : [link]
Itt a lefordított exe : [link]
Itt a virustotal ellenőrzése: 11/56 ami elég sok ahhoz képest, hogy szinte semmi olyan kódod nem irtam bele ami ezt a magas "virusos" arányt okozhatja : [link]
Sok sikert.
üdv.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!