2012-09-18 12 views
7

Ho notato qualche comportamento precisione strano che non riesco a capire, ho qualche XML:Uscite XPath .07 * 100 * 100 come 700.00000000000011 perché?

<CLD> 
    <UCRV> 
     <UCR1>.07</UCR1> 
    </UCRV> 
</CLD> 

E in un file XSLT, sto selezionando il valore come pence (o 100 pence come sembra, I don' so perché ma è ciò che il cliente vuole) come:!

<xsl:value-of select="./s0:CLD/s0:UCRV/s0:UCR1/text() * 100 * 100"/> 

ma questa è uscita come 700,00000000000011 il tipo di dati è xsd: decimale. C'è qualche precisione di default in corso qui? Posso semplicemente arrotondare il numero ma volevo solo capirlo un po 'meglio.

Grazie

+0

Prova '0,1 + 0.2' – kev

+0

Come input? Sì, funzionano bene così come 0.7. Lo capisco ora dalle altre risposte. Cheers – Rodders

risposta

5

galleggiante numeri in virgola non possono rappresentare tutto con precisione. Poiché i numeri sono memorizzati in forma binaria, a volte i numeri che sembrano facili da scrivere in decimale possono essere solo approcciati in binario. Questo è il caso di 0.07, è memorizzato internamente come 0.070000000000000011 come sembra nel tuo caso. Come regola generale, non devi mai fidarti dei valori a virgola mobile in modo da confrontarli direttamente senza arrotondare.

+0

Impressionante, grazie – Rodders

3

Questa è la matematica in virgola mobile standard. In questo c'è un numero massimo di bit per adattarsi al numero e il numero è tenuto in forma scientifica in binario. Qui 0.07 non può essere rappresentato esattamente ed è trattenuto come 0.070000000000000011.

Per ulteriori vedere molte domande su SO (anche se in altre lingue) con tag , wikipedia e What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

Fantastico, grazie – Rodders

4

Dato che le persone già spiegato, l'unico tipo numerico utilizzato in XPath è xs: double.

La funzione number() converte un valore in un doppio. Pertanto, le operazioni sui numeri in XPath 1.0 possono e talvolta comportano una perdita di precisione.

Esistono diverse soluzioni:

  1. utilizzare la funzione round(). Si possono usare anche le funzioni floor() o ceiling().

  2. Utilizzare il XSLT format-number() function() o l'istruzione <xsl:number>.

notano che XPath 2.0 supporta tutti i tipi numerici XSD, tra cui xs:decimal. Un 2.0 un'espressione XPath che non causa perdita di precisione è:

xs:decimal(0.07)*100*100 
+0

Fantastico, grazie – Rodders

+0

@ user1603018, prego. –

+1

Infatti, in XPath 2.0 il valore letterale numerico 0.07 è un xs: decimale, quindi il cast di xs: decimal non è necessario. Tuttavia, la lettura di un attributo il cui valore è "0.07" fornisce una xs: double, a meno che non si stia eseguendo l'elaborazione consapevole dello schema e lo schema dia il tipo come xs: decimal. –