2016-02-29 12 views
12

Alcune API, come la paypal API usano un tipo di stringa in JSON per rappresentare un numero decimale. Quindi "7.47" anziché 7.47.Perché dovresti usare una stringa in JSON per rappresentare un numero decimale

Perché/quando sarebbe una buona idea utilizzare il tipo di valore numero json? AFAIK il tipo di valore numerico consente una precisione infinita e una notazione scientifica.

+2

perché l'utilizzo di flottanti per la valuta causerà solo errori lungo la strada. i float NON sono utilizzabili per rappresentare valori del mondo reale come il denaro, non in ogni caso in modo affidabile. per esempio. 7.47 potrebbe essere in realtà 7.4699999923423423423 quando convertito in float. un semplice sistema che semplicemente tronca le cifre in più si tradurrà in 7.46 e ora hai perso un penny da qualche parte ... sfumature di Superman II (I?). –

+2

@MarcB Ho familiarità con il motivo per cui non si utilizzerà un float per la valuta, ma il numero JSON è effettivamente un float? A quanto ho capito, è un numero indipendente dalla lingua e potresti analizzare un numero JSON direttamente in un java 'BigDecmial' o un altro formato arbitrario di precisione in qualsiasi lingua, se così incline. – kag0

+0

dipende da come era iniziato nel sistema di PayPal. json è un mapping 1: 1 tra una stringa di testo monolitica e una struttura di dati JS. se un "numero" è memorizzato come una stringa '" ... "' nella stringa json, allora era una stringa nella struttura dati originale, o qualcosa che si associa alla stringa. –

risposta

14

Il motivo principale per trasferire valori numerici in JSON come stringhe è eliminare qualsiasi perdita di precisione o ambiguità nel trasferimento.

È vero che la specifica JSON non specifica una precisione per i valori numerici. Questo non significa che i numeri JSON abbiano una precisione infinita. Significa che la precisione numerica non è specificata, il che significa che le implementazioni JSON sono libere di scegliere qualsiasi precisione numerica conveniente per la loro implementazione o obiettivi. È questa variabilità che può essere un problema se la tua applicazione ha requisiti di precisione specifici.

La perdita di precisione in genere non è evidente nella codifica JSON del valore numerico (1.7 è piacevole e succinta) ma si manifesta nell'analisi di JSON e nelle rappresentazioni intermedie sul lato ricevente. Una funzione di analisi JSON analizza abbastanza ragionevolmente la 1.7 in un numero in virgola mobile a doppia precisione IEEE. Tuttavia, le rappresentazioni della lunghezza finita/precisione finita si imbatteranno sempre in numeri che non possono essere rappresentati con precisione. I numeri irrazionali (come pi ed e) non possono mai essere rappresentati con precisione in un sistema finito. 1.7 ha una rappresentazione finita in notazione decimale (base 10), ma in binario (base 2) è un numero irrazionale - una serie infinita di cifre.

Quindi, analizzando 1.7 in un numero in virgola mobile in memoria, la stampa del numero probabilmente restituirà qualcosa come 1.69 - non 1.7.

I consumatori del valore JSON 1.7 possono utilizzare tecniche più sofisticate per analizzare e conservare il valore in memoria, ad esempio utilizzando un tipo di dati a virgola fissa o un tipo di dati "string int" con precisione arbitraria, ma ciò non sarà interamente eliminare lo spettro della perdita di precisione nella conversione per alcuni numeri. E la realtà è che pochissimi parser JSON si preoccupano di misure così estreme, poiché i vantaggi per la maggior parte delle situazioni sono bassi e i costi di memoria e CPU sono elevati.

Quindi, se si desidera inviare un valore numerico preciso a un consumatore e non si desidera la conversione automatica del valore nella tipica rappresentazione numerica interna, la soluzione migliore è spedire il valore numerico come stringa e dire al consumatore esattamente come deve essere elaborata quella stringa se e quando operazioni numeriche devono essere eseguite su di essa.

Ad esempio: In alcuni produttori JSON (JRuby, per uno), i valori BigInteger vengono automaticamente inviati a JSON come stringhe, in gran parte perché l'intervallo e la precisione di BigInteger è molto più grande del float IEEE a doppia precisione. Ridurre il valore di BigInteger da raddoppiare per ottenere un valore numerico JSON spesso perde cifre significative.

Inoltre, la specifica JSON (http://www.json.org/) indica esplicitamente che NaN e Infiniti (INF) non sono validi per i valori numerici JSON. Se è necessario esprimere questi elementi marginali, non è possibile utilizzare il numero JSON. Devi usare una stringa o una struttura di oggetti.

Infine, c'è un altro aspetto che può portare a scegliere di inviare dati numerici come stringhe: controllo della formattazione del display. Gli zeri iniziali e gli zeri finali sono insignificanti rispetto al valore numerico. Se si invia il valore del numero JSON 2.10 o 004, dopo la conversione in forma numerica interna verranno visualizzati come 2.1 e 4.

Se si inviano dati che verranno visualizzati direttamente all'utente, è probabile che si desideri che le cifre in denaro siano allineate correttamente sullo schermo, allineate decimali. Un modo per farlo è rendere il cliente responsabile della formattazione dei dati per la visualizzazione. Un altro modo per farlo è di fare in modo che il server formatta i dati per la visualizzazione. È più semplice per il client visualizzare le informazioni sullo schermo, ma ciò può rendere difficile estrarre il valore numerico dalla stringa se il client deve anche eseguire calcoli sui valori.

+0

Non sottovalutare il significato dei numeri irrazionali: ci sono molti più numeri irrazionali che numeri razionali! Entrambi sono insiemi infiniti, ma la misura degli irrazionali è maggiore della misura dei razionali. Chiedi al tuo professore di matematica locale Porta il caffè. :> – dthorpe

+1

Puoi fornire altri esempi di client che perdono precisione nella codifica? Jackson in Java, ad esempio, convertirà felicemente un decimale json in un BigDecimal senza perdere precisione. È frustrante rendere la propria API meno accurata (non è una stringa, è un numero, che è supportato da json) solo perché alcuni client senza nome stanno facendo quello che considererei la "cosa sbagliata" quando viene assegnato un numero json. –

0

Sintetica versione

Proprio citando @ di dthorpe risposta, come credo che questo sia il punto più importante:

Inoltre, le specifiche JSON (http://www.json.org/) afferma esplicitamente che NaNs e Infinities (INFS) non sono validi per i valori numerici JSON. Se è necessario esprimere questi elementi marginali, non è possibile utilizzare il numero JSON. Devi usare una stringa o una struttura di oggetti.

Problemi correlati