Ho sviluppato un'applicazione che si integra con SPS 2003, per la gestione di tipi di dato Currency. In fase di Testing BlackBox del' applicazione ho inserito, in corrispondenza dei Currency, grandi cifre decimali (EX: 1234567890123456).
Questo specifico test ha evidenziato delle anomalie replicabili creando una semplice lista in Sahrepoint composta da una colonna di tipo Currency ed una colonna di tipo Number:
L'immagine mostra la lista inizializzata con valori significativi, da questa lista prendiamo in esame la quarta riga a partire dall'alto. Sebbene le colonne "currency" e "number" vengano visualizzate come cifre numeriche senza apparenti problemi, in fase di inserimento il numero inserito era differente rispetto a quello visualizzato. Infatti a fronte dell'inserimento della cifra "1234567890123456" mi ritrovo visualizzata la cifra "1234567890123460" trattandosi di Currency ovvero "Moneta" trovo un'arrotondamento per eccesso di 4 euro ;). La stessa cosa capita anche al tipo di dato Number.
Visto il problema, analizzo le possibili cause, focalizzando l'attenzione sui tipi di dato Currency (quello che mi interessa). Il valore di questo tipo di dato viene gestito con metodi della classe "Number", che a sua volta corrisponde ad un System.Double del .NET Framework. Per fissare meglio le affermazioni rimando alle pagina di MSDN relativa l'Enum SPFieldType e relativa la Classe SPFieldCurrency del Namespace "Microsoft.Sharepoint".
Avendo scoperto il tipo di dato base System.Double, ho iniziato ad implementare alcuni piccoli e semplici test su questo tipo realizzando una stupida applicazione che:
Dim f As Double = 999999999999999
Dim g As Double = 1234567890123456
Console.WriteLine("f: " & f.ToString)
Console.WriteLine("g: " & g.ToString)
Mandando in esecuzione questa piccola applicazione si nota che il primo dato viene mostrato nella notazione decimale mentre il secondo viene mostrato nella notazione in virgola mobile, altra cosa fondamentale il secondo dato è 1,234567890123456E+15 che nella notazione decimale corrisponde a 1234567890123460 propio il valore decimale arrotondato della lista di SahrePoint visto prima. Abbiamo spostato il problema dal tipo di dato Currency al System.Double di .NET.
Da una semplicissima ricerca su google ho scoperto che System.Double (.NET framework) è conforme allo standard IEEE per il calcolo in virgola mobile (IEEE 754), la gestione secondo lo standard di questi numeri per la precisione doppia é:
L'imagine mostra la distribuzione dei 64 bit che compongono la gestione dei double a doppia precisione fonte wikipedia essa infatti è stata estrapolata dal sito, per cui non garantisco che ci sia corrispondenza 1 a 1 con la rappresentazione dei double del Framework .NET, MSDN comunque dice:
"The Double value type represents a double-precision 64-bit number with values ranging from negative 1.79769313486232e308 to positive 1.79769313486232e308, as well as positive or negative zero, PositiveInfinity, NegativeInfinity, and Not-a-Number (NaN).
Double complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic." (fonte MSDN)
Le informazioni date fin d'ora, sopratutto quelle recuperate da wikipedia, sono si dettagliate ma non sufficienti a capire a fondo il problema, ho eseguito per cui altre ricerche, ho trovato questa voce tratta da wikipedia (inglese questa volta) dei numeri in virgola mobile a doppia precisione, da queta voce estrapolo una parte significativa:
"... With the 52 bits of the fraction mantissa appearing in the memory format the total precision is therefore 53 bits (approximately 16 decimal digits, log10(253)). ... " (fonte wikipedia)
Il testo dice chiaramente che: la precisione totale raggiungibile sono "approssimativamente", gli interi composti da 16 cifre decimali. Aggiungo che i numeri eccednti tale limite vengono arrotondati al minimo numero rappresentabile maggiore della cifra data. Se ora riprendiamo il codice della piccola "Console Application" notiamo che esso cerca di rappresentare un numero composto appunto da 16 cifre decimali (1234567890123456), il che comporta l'arrotondamento. Sempre estratto dalla voce wikipedia faccio notare l'uguaglianza del range di numeri rappresentabili riportato anche da MSDN:
"0x7fef ffff ffff ffff ~ 1.7976931348623157 x 10308 (Max Double)" (fonte wikipedia)
Questo è quanto, vi consiglio per cui attenzione nell'uso di cifre composte da un numero di interi superiore a 15 sopratutto se dovete poi effettuare delle operazioni su di esse, sia quando state utilizzando Sharepoint ma anche quando svilupate utilizzando il .NET framework.