Quasi tutti i linguaggi di programmazione usano delle funzioni di basso livello per velocizzare i conti, ma questo implica portarsi dietro i limiti dei processori ad esempio in linea teorica un computer a 32bit può gestire solo numeri fino a 232, mentre computer a 64 bit possono gestire 264.
Ogni software opera un certo grado di approssimazione per numeri molto grandi, quindi bisogna scrivere delle funzioni particolari che possano elaborare numeri senza limiti od errori.
Qui di seguito trovate il codice per fare somma (bigSum), sottrazione (bigSub), moltiplicazione (bigMultiply) e divisione (bigDivide) e anche per capire se un numero è più grande di un altro (bigGreater).
Con queste funzioni potrete gestire tutti i numeri senza alcune errore e di qualunque dimensione.
function bigAdd a1, a2 put reverse2(a1) into b1 put reverse2(a2) into b2 put 0 into mem if length(b1) < length(b2) then put b1 into temp put b2 into b1 put temp into b1 end if repeat while b2 is not empty put (char 1 of b1) + (char 1 of b2) + mem into ppp if length(ppp) = 1 then put 0 into mem put ppp before rrr else put 1 into mem put char 2 of ppp before rrr end if delete char 1 of b1 delete char 1 of b2 end repeat repeat while (b1 is not empty) put mem + (char 1 of b1) into ppp if length(ppp) = 1 then put 0 into mem put ppp before rrr else put 1 into mem put char 2 of ppp before rrr end if delete char 1 of b1 end repeat if mem = 1 then put 1 before rrr else put b1 before rrr end if return rrrend bigAdd
function reverse2 temp repeat for each char tChar in temp put tChar before temp2 end repeat return temp2end reverse2
function bigMultiply a1,a2 put reverse2(a1) into a1 put 0 into temp repeat for each char tChar in a1 repeat with i=1 to tChar put bigAdd(temp,a2) into temp end repeat put 0 after a2 end repeat return tempend bigMultiply
function bigGreater a1,a2 #compare two bignumbers: #return true if n1 > n2 #return false if n1 < n2 #return empty if n1 = n2 if length(a1) is not length(a2) then return ( length(a1) > length(a2) ) #this is evalueted true or false else if a1 = a2 then return empty else repeat while ((char 1 of a1) = (char 1 of a2) ) delete char 1 of a1 delete char 1 of a2 end repeat return ((char 1 of a1) > (char 1 of a2)) #this is evalueted true or false end if end ifend bigGreater
function bigSub a1,a2 #substract the smallest big number from the largest one if bigGreater(a2,a1) then put a1 into temp put a2 into a1 put temp into a2 end if put reverse2(a1) into a1 put reverse2(a2) into a2 put 0 into mem repeat while (a2 is not empty) put (char 1 of a1) - mem + 10 - (char 1 of a2) into minus if length(minus) = 1 then put 1 into mem put minus before rrr else put 0 into mem put char 2 of minus before rrr end if delete char 1 of a1 delete char 1 of a2 end repeat repeat while (a1 is not empty) put char 1 of a1 + 10 - mem into minus if length(minus) = 1 then put 1 into mem put minus before rrr else put 0 into mem put char 2 of minus before rrr end if delete char 1 of a1 end repeat #remove inital zeros repeat while (char 1 of rrr is "0") delete char 1 of rrr end repeat return rrrend bigSub
function bigDivide a1,a2 #output is a block of two numbers "quotient , remainder" if bigGreater(a2,a1) then return ("0 , " & a1) end if if a1 = a2 then return "1 , 0" end if put 0 into count repeat while (bigGreater(a1,a2)) put bigSub(a1,a2) into a1 put bigAdd(1,count) into count end repeat if a1 = a2 then put bigAdd(count,1) into count put 0 into a1 end if return (count & " , " & a1)end bigDivide
Ad esempio per fare la sottrazione "123456789123456789123456789 - 1234567891023456789", basta usare :
bigSub(123456789123456789123456789, 1234567891023456789) = 123456787888888898100000000mentre per molti altri software il risultato è 1.23456787888889E+26 che è sbagliato!
La spiegazione è che molti software approssimano quando non hanno più bit a disposizione, quindi usano solo le prime 15 cifre e poi aggiungo zeri. In questo modo danno come risultato
1.23456787888889E+26
che significa
123456787888889000000000000
mentre il risultato corretto è
123456787888888898100000000
L'errore è di 101'900'000'000, vi sembra un piccolo errore?
Nessun commento:
Posta un commento