Differenze tra le versioni di "Gestire numeri superiori al limite massimo supportato dal tipo Long"
(Creata pagina con "Come è noto, in Gambas il tipo di variabile ''Long'' in Gambas è capace di contenere valori ''positivi'' non superiori al numero ''9.223.372.036.854.775.807''. <SUP>[...") |
|||
(2 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 1: | Riga 1: | ||
− | Come è noto, in Gambas il tipo di variabile ''Long'' in Gambas è capace di contenere valori ''positivi'' non superiori al numero ''9.223.372.036.854.775.807''. <SUP>[[[#Note| | + | Come è noto, in Gambas il tipo di variabile ''Long'' in Gambas è capace di contenere valori ''positivi'' non superiori al numero ''9.223.372.036.854.775.807''. <SUP>[[[#Note|nota 1]]]</sup> |
− | Per poter ottenere dalla somma (o dalla moltiplicazione) di due o più numeri un risultato superiore al limite massimo rappresentabile in Gambas dal valore ''Long'', si potranno adottare alcune modalità | + | Per poter ottenere dalla somma (o dalla moltiplicazione) di due o più numeri un risultato superiore al limite massimo rappresentabile in Gambas dal valore ''Long'', si potranno adottare alcune modalità <SUP>[[[#Note|nota 2]]]</sup><SUP>[[[#Note|nota 3]]]</sup> che di seguito descriveremo. |
− | ==Uso della Classe Classe | + | ==Uso della Classe Classe ''BigInt'' del Componente ''gb.gmp''== |
− | Per poter superare i limiti del suo nativo tipo ''Long'', Gambas fornisce un apposito Componente, denominato "''[http://gambaswiki.org/wiki/comp/gb.gmp?en gb.gmp]''". In particolare questo Componente è costituito da due Classi: | + | Per poter superare i limiti del suo nativo tipo ''Long'', Gambas fornisce un apposito Componente, denominato "''[http://gambaswiki.org/wiki/comp/gb.gmp?en gb.gmp]''". In particolare questo Componente è costituito da due Classi: ''BigInt'', che rappresenta un numero intero con numero potenziale illimitato di cifre, e "''Rational'' ", dedicato alla gestione dei numeri razionali. |
Mostriamo un semplice esempio pratico di utilizzo della Classe ''BigInt'' con le quattro operazioni basilari: | Mostriamo un semplice esempio pratico di utilizzo della Classe ''BigInt'' con le quattro operazioni basilari: | ||
− | + | Public Sub Main() | |
− | + | Dim s1, s2 As String | |
− | + | Dim addi, sott, molt, divi As BigInt | |
s1 = "9999999999999999999999999999999999999999999999999999999999999999999999999999" | s1 = "9999999999999999999999999999999999999999999999999999999999999999999999999999" | ||
Riga 25: | Riga 25: | ||
Print divi | Print divi | ||
− | + | End | |
− | ==Uso della funzione esterna | + | ==Uso della funzione esterna "sprintf()"== |
− | Questa modalità prevede la conversione della somma di due ''Long'' di Gambas nel formato del tipo ''unsigned long long'' <SUP>[[[#Note| | + | Questa modalità prevede la conversione della somma di due ''Long'' di Gambas nel formato del tipo ''unsigned long long'' <SUP>[[[#Note|nota 4]]]</sup>, e, affinché possa essere rappresentato dalle risorse di Gambas, si effettuerà la conversione del risultato in una stringa (ma comunque visivamente rappresentato in forma decimale) mediante la funzione esterna ''sprintf( )'' di C. |
Il risultato della somma dei due valori non potrà comunque superare il valore massimo rappresentabile del predetto tipo ''unsigned long long'' del linguaggio C. | Il risultato della somma dei due valori non potrà comunque superare il valore massimo rappresentabile del predetto tipo ''unsigned long long'' del linguaggio C. | ||
Riga 40: | Riga 40: | ||
− | + | Public Sub Main() | |
− | + | Dim l As Long | |
− | + | Dim p As Pointer | |
− | <FONT Color=gray>' '' | + | <FONT Color=gray>' ''Assegna alla variabile di tipo "Long" il valore massimo assegnabile per un tipo "Long" in Gambas:''</font> |
l = 9223372036854775807 | l = 9223372036854775807 | ||
p = Alloc(24) | p = Alloc(24) | ||
− | <FONT Color=gray>' '' | + | <FONT Color=gray>' ''Moltiplica il valore della variabile per 2. Convertiamo il risultato nel tipo 'unsigned long long' del C.'' |
− | ' ''Al termine | + | ' ''Al termine converte il risultato in una stringa che sarà posta mediante la funzione 'sprintf()' nell'area di memoria puntata dal 'Puntatore':''</font> |
<FONT Color=#B22222>sprintf(p, "%llu", l * 2)</font> | <FONT Color=#B22222>sprintf(p, "%llu", l * 2)</font> | ||
If String@(p) = "0" Then Error.Raise("Errore: è stato superato il valore massimo (18446744073709551615ULL) del tipo 'unsigned long long' del C !") | If String@(p) = "0" Then Error.Raise("Errore: è stato superato il valore massimo (18446744073709551615ULL) del tipo 'unsigned long long' del C !") | ||
Riga 59: | Riga 59: | ||
Print "Risultato superiore al 'Long' ottenuto: "; String@(p) | Print "Risultato superiore al 'Long' ottenuto: "; String@(p) | ||
− | <FONT Color=gray>' '' | + | <FONT Color=gray>' ''Libera la memoria precedentemente riservata e si assicura che il Puntatore non punti ad alcun indirizzo rilevante di memoria:''</font> |
Free(p) | Free(p) | ||
p = 0 | p = 0 | ||
− | + | End | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
===Caso in cui il numero è espresso in rappresentazione "binaria"=== | ===Caso in cui il numero è espresso in rappresentazione "binaria"=== | ||
− | Qualora il valore numerico, superiore al limite massimo rappresentabile in Gambas dal valore ''Long'', sia espresso in rappresentazione ''binaria'', si potrà adottare un'apposita funzione esterna, da noi scritta in puro C, con la quale si | + | Qualora il valore numerico, superiore al limite massimo rappresentabile in Gambas dal valore ''Long'', sia espresso in rappresentazione ''binaria'', si potrà adottare un'apposita funzione esterna, da noi scritta in puro C, con la quale si farà uso della funzione esterna "strtoul()", dichiarata nel file header ''/usr/include/stdlib.h''. Tale funzione esterna "strtoul()" converte un numero, scritto in formato stringa, in un valore numerico di tipo ''unsigned long int'' del linguaggio C <SUP>[[[#Note|nota 5]]]</sup>, qualunque sia la ''base'', la quale sarà specificata nel suo terzo parametro. |
+ | <BR>Il valore binario infine sarà convertito mediante la funzione esterna "sprintf()" in una rappresentazione di tipo stringa, ma visivamente in forma decimale. | ||
Mostriamo un esempio pratico: | Mostriamo un esempio pratico: | ||
Riga 125: | Riga 78: | ||
− | + | Public Sub Main() | |
− | + | Dim bnr, rit As String | |
CreaSo() | CreaSo() | ||
Riga 138: | Riga 91: | ||
Print rit | Print rit | ||
− | + | End | |
− | + | Private Procedure CreaSo() | |
File.Save("/tmp/lib.c", "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n" & | File.Save("/tmp/lib.c", "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n" & | ||
Riga 153: | Riga 106: | ||
Shell "gcc -o /tmp/lib.so /tmp/lib.c -shared -fPIC" Wait | Shell "gcc -o /tmp/lib.so /tmp/lib.c -shared -fPIC" Wait | ||
− | + | End | |
− | |||
=Note= | =Note= | ||
− | [1] Come è noto, il tipo nativo ''Long'' di Gambas corrisponde sostanzialmente al tipo "''signed long int''" del linguaggio C (vedi anche il file header | + | [1] Come è noto, il tipo nativo ''Long'' di Gambas corrisponde sostanzialmente al tipo "''signed long int'' " del linguaggio C (vedi anche il file header ''/usr/include/limits.h''). |
− | [2] Vedere anche: [[ | + | [2] Vedere anche: [[Operazioni con precisione quadrupla a 128-bit con numeri in virgola mobile mediante la libreria quadmath.h]] |
[3] Interessante vedere anche la libreria esterna "''[http://www.gambas-it.org/smf/index.php?topic=5589.msg41269#msg41269 BigNumber]''", autori Davide Zanin e Frhack3r. | [3] Interessante vedere anche la libreria esterna "''[http://www.gambas-it.org/smf/index.php?topic=5589.msg41269#msg41269 BigNumber]''", autori Davide Zanin e Frhack3r. | ||
− | [4] Il tipo ''unsigned long long'' è specificato nel file header | + | [4] Il tipo ''unsigned long long'' è specificato nel file header ''/usr/include/limits.h''. |
− | [5] Il tipo ''unsigned long int'' è specificato nel file header | + | [5] Il tipo ''unsigned long int'' è specificato nel file header ''/usr/include/limits.h''. |
Versione attuale delle 16:47, 1 lug 2024
Come è noto, in Gambas il tipo di variabile Long in Gambas è capace di contenere valori positivi non superiori al numero 9.223.372.036.854.775.807. [nota 1]
Per poter ottenere dalla somma (o dalla moltiplicazione) di due o più numeri un risultato superiore al limite massimo rappresentabile in Gambas dal valore Long, si potranno adottare alcune modalità [nota 2][nota 3] che di seguito descriveremo.
Indice
Uso della Classe Classe BigInt del Componente gb.gmp
Per poter superare i limiti del suo nativo tipo Long, Gambas fornisce un apposito Componente, denominato "gb.gmp". In particolare questo Componente è costituito da due Classi: BigInt, che rappresenta un numero intero con numero potenziale illimitato di cifre, e "Rational ", dedicato alla gestione dei numeri razionali.
Mostriamo un semplice esempio pratico di utilizzo della Classe BigInt con le quattro operazioni basilari:
Public Sub Main() Dim s1, s2 As String Dim addi, sott, molt, divi As BigInt s1 = "9999999999999999999999999999999999999999999999999999999999999999999999999999" s2 = "8888888888888888888888888888888888888888888888888888888888888888888888888888" addi = BigInt.FromString(s1) + BigInt.FromString(s2) sott = BigInt.FromString(s1) - BigInt.FromString(s2) molt = BigInt.FromString(s1) * BigInt.FromString(s2) divi = BigInt.FromString(s1) / BigInt.FromString(s2) Print addi Print sott Print molt Print divi End
Uso della funzione esterna "sprintf()"
Questa modalità prevede la conversione della somma di due Long di Gambas nel formato del tipo unsigned long long [nota 4], e, affinché possa essere rappresentato dalle risorse di Gambas, si effettuerà la conversione del risultato in una stringa (ma comunque visivamente rappresentato in forma decimale) mediante la funzione esterna sprintf( ) di C.
Il risultato della somma dei due valori non potrà comunque superare il valore massimo rappresentabile del predetto tipo unsigned long long del linguaggio C.
Mostriamo un esempio:
' int sprintf(char *str, const char *format, ...) ' Sends formatted output to a string pointed to, by str. Private Extern sprintf(strP As Pointer, formatS As String, lo As Long) As Integer In "libc:6" Public Sub Main() Dim l As Long Dim p As Pointer ' Assegna alla variabile di tipo "Long" il valore massimo assegnabile per un tipo "Long" in Gambas: l = 9223372036854775807 p = Alloc(24) ' Moltiplica il valore della variabile per 2. Convertiamo il risultato nel tipo 'unsigned long long' del C. ' Al termine converte il risultato in una stringa che sarà posta mediante la funzione 'sprintf()' nell'area di memoria puntata dal 'Puntatore': sprintf(p, "%llu", l * 2) If String@(p) = "0" Then Error.Raise("Errore: è stato superato il valore massimo (18446744073709551615ULL) del tipo 'unsigned long long' del C !") Print "Valore massimo rappresentabile dal 'Long': 9223372036854775807\n" Print "Risultato superiore al 'Long' ottenuto: "; String@(p) ' Libera la memoria precedentemente riservata e si assicura che il Puntatore non punti ad alcun indirizzo rilevante di memoria: Free(p) p = 0 End
Caso in cui il numero è espresso in rappresentazione "binaria"
Qualora il valore numerico, superiore al limite massimo rappresentabile in Gambas dal valore Long, sia espresso in rappresentazione binaria, si potrà adottare un'apposita funzione esterna, da noi scritta in puro C, con la quale si farà uso della funzione esterna "strtoul()", dichiarata nel file header /usr/include/stdlib.h. Tale funzione esterna "strtoul()" converte un numero, scritto in formato stringa, in un valore numerico di tipo unsigned long int del linguaggio C [nota 5], qualunque sia la base, la quale sarà specificata nel suo terzo parametro.
Il valore binario infine sarà convertito mediante la funzione esterna "sprintf()" in una rappresentazione di tipo stringa, ma visivamente in forma decimale.
Mostriamo un esempio pratico:
Library "/tmp/lib" ' char * bindecstring(const char * binario) ' Converte un numero binario in numero in rappresentazione decimale e di tipo string. Private Extern bindecstring(binario As String) As String Public Sub Main() Dim bnr, rit As String CreaSo() ' Il valore espresso in rappresentazione "binaria" da mostrare in forma decimale, ma di tipo stringa: bnr = "1111111111111111111111111111111111111111111111111111111111111111" rit = bindecstring(bnr) Print rit End Private Procedure CreaSo() File.Save("/tmp/lib.c", "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n" & "char * bindecstring(const char * binario) {\n\n" & " unsigned long int ris;\n" " char *rit = calloc(72, sizeof(char));\n\n" & " ris = strtoul(binario, NULL, 2);\n" & " sprintf(rit, \"%lu\", ris);\n\n" & " return rit;\n\n}") Shell "gcc -o /tmp/lib.so /tmp/lib.c -shared -fPIC" Wait End
Note
[1] Come è noto, il tipo nativo Long di Gambas corrisponde sostanzialmente al tipo "signed long int " del linguaggio C (vedi anche il file header /usr/include/limits.h).
[2] Vedere anche: Operazioni con precisione quadrupla a 128-bit con numeri in virgola mobile mediante la libreria quadmath.h
[3] Interessante vedere anche la libreria esterna "BigNumber", autori Davide Zanin e Frhack3r.
[4] Il tipo unsigned long long è specificato nel file header /usr/include/limits.h.
[5] Il tipo unsigned long int è specificato nel file header /usr/include/limits.h.