Differenze tra le versioni di "Operazioni con precisione quadrupla a 128-bit con numeri in virgola mobile mediante la libreria quadmath.h"

Da Gambas-it.org - Wikipedia.
Riga 1: Riga 1:
 
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'').
 
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 rapresenta un valore in virgola mobile con precisione ''doppia''. La precisione del ''Float'' è di 52 cifre binarie che sono 16 cifre decimali (2^-52). Questo vuole dire che se si aggiunge un numero positivo minore di 2E-16 a 1.0, allora il risultato sarà precisamente 1.0 .
+
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). Questo vuole dire che se si aggiunge un numero positivo minore di 2E-16 a 1.0, allora il risultato sarà precisamente 1.0 .
  
  

Versione delle 10:17, 22 ott 2016

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). Questo vuole dire che se si aggiunge un numero positivo minore di 2E-16 a 1.0, allora il risultato sarà precisamente 1.0 .


Prestazioni di precisioni superiori non sono possibili in Gambas con i tipi di valore nativi.

Possiamo ovviare a questo limite, utilizzando la libreria "quadmath.h" che 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 codivisa che consenta di effettuare le quattro principali operazioni fra due numeri in virgola mobile.

La libreria condivisa, da noi creata, possiede un'unica funzione, chiamata

char * Float128q(int dec, char *num1, char *num2, char *opera)

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 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
 Dim s As String
 
' Va a creare la nostra apposita libreria dinamica esterna .so per la gestione delle risorse della libreria esterna "quadmath.h":
  CrealibFloat128q()  
 
' Per i numeri in virgola mobile si deve usare la virgola separatrice della parte decimale:
  s = Float128q(32, "5,123456789123456789", "3,123456789", operazione[3])
 
  Print "Risultato: "; s
   
End


Private Procedure CrealibFloat128q()
 
' Scrive il codice sorgente della nostra apposita libreria dinamica esterna:
  File.Save("/tmp/libfloat128q.c", "#include </usr/lib/gcc/x86_64-linux-gnu/4.8/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}")
  
' Genera la nostra apposita libreria dinamica esterna:
  Shell "gcc -o /tmp/libfloat128q.so /tmp/libfloat128q.c -shared -fPIC -lquadmath" Wait
  
End



Riferimenti