Differenze tra le versioni di "Operazioni con precisione quadrupla a 128-bit con numeri in virgola mobile mediante la libreria quadmath.h"
Riga 28: | Riga 28: | ||
Private Extern Float128q(dcm As Integer, num1 As String, num2 As String, opera As String) As String | Private Extern Float128q(dcm As Integer, num1 As String, num2 As String, opera As String) As String | ||
Bisogna ricordare che per numeri in virgola mobile, passati nel secondo e terzo argomento della funzione esterna ''Float128q( )'', il segno separatore della parte intera dalla parte decimale dovrà essere quello ''locale'', ossia da noi la <SPAN Style="text-decoration:underline">''virgola''</span>. | Bisogna ricordare che per numeri in virgola mobile, passati nel secondo e terzo argomento della funzione esterna ''Float128q( )'', il segno separatore della parte intera dalla parte decimale dovrà essere quello ''locale'', ossia da noi la <SPAN Style="text-decoration:underline">''virgola''</span>. | ||
− | |||
Mostriamo dunque un esempio pratico, nel quale scegliamo di far effettuare una ''divisione'' fra i due numeri passati, e di ottenere un risultato avente la parte decimale formata da 32 numeri: | Mostriamo dunque un esempio pratico, nel quale scegliamo di far effettuare una ''divisione'' fra i due numeri passati, e di ottenere un risultato avente la parte decimale formata da 32 numeri: | ||
Riga 38: | Riga 37: | ||
− | + | Public Sub Main() | |
− | |||
− | |||
− | |||
+ | Dim operazione As String[] = ["add", "sot", "mol", "div"] <FONT Color=gray>' ''Imposta gli identificatori delle 4 operazioni principali: "addizione", "sottrazione", "moltiplicazione" e "divisione"''</font> | ||
+ | Dim ver, s As String | ||
+ | |||
<FONT Color=gray>' ''Cerca la cartella della versione di gcc contenente il file header "quadmath.h":''</font> | <FONT Color=gray>' ''Cerca la cartella della versione di gcc contenente il file header "quadmath.h":''</font> | ||
ver = Versione() | ver = Versione() | ||
Riga 54: | Riga 53: | ||
Print "Risultato: "; s | Print "Risultato: "; s | ||
− | + | End | |
− | + | Private Function Versione() As String | |
− | + | Dim dd As String[] | |
− | + | Dim percorso, d As String | |
− | + | ||
percorso = "/usr/lib/gcc/x86_64-linux-gnu/" | percorso = "/usr/lib/gcc/x86_64-linux-gnu/" | ||
Riga 72: | Riga 71: | ||
Return d | Return d | ||
− | + | End | |
− | + | Private Procedure CrealibFloat128q(v As String) | |
<FONT Color=gray>' ''Scrive il codice sorgente della nostra apposita libreria dinamica esterna:''</font> | <FONT Color=gray>' ''Scrive il codice sorgente della nostra apposita libreria dinamica esterna:''</font> | ||
Riga 116: | Riga 115: | ||
Shell "gcc -o /tmp/libfloat128q.so /tmp/libfloat128q.c -shared -fPIC -lquadmath" Wait | Shell "gcc -o /tmp/libfloat128q.so /tmp/libfloat128q.c -shared -fPIC -lquadmath" Wait | ||
− | + | End | |
− | |||
Versione delle 15:27, 21 giu 2024
Come è noto, in Gambas nelle operazioni con numeri in virgola mobile il tipo di valore che consente la più alta precisione è il Float (che nel C corrisponde al tipo chiamato double).
Questo tipo di valore nativo nei sistemi a 64-bit occupa 8 byte (64-bit) e rappresenta un valore in virgola mobile con precisione doppia. La precisione del Float è di 52 cifre binarie che sono 16 cifre decimali (2^-52).
Precisioni superiori non sono possibili in Gambas con i tipi di valore nativi.
Superare i limiti di Gambas della doppia precisione del Float con i numeri in virgola mobile mediante la libreria "quadmath.h"
Possiamo ovviare al limite di Gambas della doppia precisione del Float con i numeri in virgola mobile, utilizzando la libreria "quadmath.h", la quale fornisce una precisione quadrupla a 128-bit (16 byte).
Potremo utilizzare in Gambas le risorse e le potenzialità di detta libreria, realizzando un'apposita libreria dinamica condivisa esterna .so.
Pur fornendo la libreria quadmath.h proprie funzioni matematiche e trigonometriche, nell'esempio che faremo di seguito ci limiteremo a creare una libreria condivisa che consenta di effettuare le quattro principali operazioni (addizione, sottrazione, moltiplicazione e divisione) fra due numeri in virgola mobile.
La libreria condivisa, da noi creata, possiede un'unica funzione, così dichiarata:
char * Float128q(int dec, char *num1, char *num2, char *opera)
e contenente le righe di codice per effettuare, a seconda dell'identificativo passato, una delle quattro operazioni predette.
Riguardo ai suoi parametri:
- il primo è un intero che rappresenta il numero di decimali dopo la virgola che saranno mostrati;
- il secondo è un Puntatore ad un vettore di valori di tipo carattere che rappresenta il primo numero oggetto dell'operazione;
- il terzo è un Puntatore ad un vettore di valori di tipo carattere che rappresenta il secondo numero oggetto dell'operazione;
- il quarto è un Puntatore ad un vettore di valori di tipo carattere che rappresenta l'identificatore dell'operazione prescelta da far compiere.
La funzione restituisce un Puntatore ad un vettore di valori di tipo carattere che rappresenta il risultato dell'operazione da noi scelta.
Tutto ciò in Gambas sarà così dichiarato con Extern:
Private Extern Float128q(dcm As Integer, num1 As String, num2 As String, opera As String) As String
Bisogna ricordare che per numeri in virgola mobile, passati nel secondo e terzo argomento della funzione esterna Float128q( ), il segno separatore della parte intera dalla parte decimale dovrà essere quello locale, ossia da noi la virgola.
Mostriamo dunque un esempio pratico, nel quale scegliamo di far effettuare una divisione fra i due numeri passati, e di ottenere un risultato avente la parte decimale formata da 32 numeri:
Library "/tmp/libfloat128q" ' char * Float128q(int dcm, char *num1, char *num2, char *opera) ' La funzione contenuta nella nostra libreria dinamica per la gestione delle risorse della libreria esterna "quadmath.h" Private Extern Float128q(dcm As Integer, num1 As String, num2 As String, opera As String) As String Public Sub Main() Dim operazione As String[] = ["add", "sot", "mol", "div"] ' Imposta gli identificatori delle 4 operazioni principali: "addizione", "sottrazione", "moltiplicazione" e "divisione" Dim ver, s As String
' Cerca la cartella della versione di gcc contenente il file header "quadmath.h": ver = Versione() ' Va a creare la nostra apposita libreria dinamica esterna .so per la gestione delle risorse della libreria esterna "quadmath.h": CrealibFloat128q(ver) ' Per i numeri in virgola mobile si deve usare la "virgola" separatrice della parte decimale da quella intera: s = Float128q(32, "5,123456789123456789", "3,123456789", operazione[3]) Print "Risultato: "; s End Private Function Versione() As String Dim dd As String[] Dim percorso, d As String percorso = "/usr/lib/gcc/x86_64-linux-gnu/" dd = Dir(percorso, Null, gb.Directory).Sort(gb.Descent) For Each d In dd If Exist(percorso &/ d &/ "quadmath.h") Then Exit Next Return d End Private Procedure CrealibFloat128q(v As String) ' Scrive il codice sorgente della nostra apposita libreria dinamica esterna: File.Save("/tmp/libfloat128q.c", "#include </usr/lib/gcc/x86_64-linux-gnu" &/ v &/ "include/quadmath.h>\n" & "#include <stdio.h>\n" & "#include <string.h>" & "\n\n" & "char buf[128];" & "\n\n\n" & "char * Float128q(int dcm, char *num1, char *num2, char *opera) {" & "\n\n" & " char str[4];\n" & " char dest[16] = \"%+-#*.\";\n" & " __float128 fl1, fl2, ris;" & "\n\n\n" & " sprintf(str, \"%d\", dcm);\n" & " strcat(dest, str);\n" & " strcat(dest, \"Qe\");" & "\n\n" & " fl1 = strtoflt128(num1, NULL);\n" & " fl2 = strtoflt128(num2, NULL);" & "\n\n" & " if (strcmp(opera, \"add\") == 0 ) {\n" & " ris = fl1 + fl2;\n }" & "\n\n" & " if (strcmp(opera, \"sot\") == 0 ) {\n" & " ris = fl1 - fl2;\n }" & "\n\n" & " if (strcmp(opera, \"mol\") == 0 ) {\n" & " ris = fl1 * fl2;\n }" & "\n\n" & " if (strcmp(opera, \"div\") == 0 ) {\n" & " ris = fl1 / fl2;\n }" & "\n\n\n" & " quadmath_snprintf(buf, 128, dest, ris); "\n\n" & " return buf;\n\n}") ' Genera la nostra apposita libreria dinamica esterna: Shell "gcc -o /tmp/libfloat128q.so /tmp/libfloat128q.c -shared -fPIC -lquadmath" Wait End