2012-09-18 21 views
7

he notado algún comportamiento precisión extraño que no puedo entender, tengo algo de XML:XPath salidas .07 * 100 * 100 como 700.00000000000011 ¿por qué?

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

Y en un archivo XSLT, estoy seleccionando el valor como peniques (o 100 peniques como parece, I don' sé por qué, pero es lo que el cliente quiere) como:

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

pero esta es la salida como 700.00000000000011 el tipo de datos es xsd: decimal. ¿Hay alguna precisión predeterminada aquí? Simplemente puedo redondear el número, pero solo quería entenderlo un poco mejor.

Gracias

+0

Try '+ 0,1 0.2' – kev

+0

Como entrada? Sí, funcionan bien, al igual que 0.7. Lo entiendo ahora por las otras respuestas. Saludos – Rodders

Respuesta

5

Los números de coma flotante no pueden representar todo con precisión. Dado que los números se almacenan en forma binaria, los números que parecen ser fáciles de escribir en decimales en realidad solo se abordan en binario algunas veces. Este es el caso con 0.07, se almacena internamente como 0.070000000000000011 como parece en su caso. Como regla general, nunca debe confiar en los valores de coma flotante para compararlos directamente sin redondeo.

+0

Impresionante, gracias – Rodders

3

Esto es matemáticas de coma flotante estándar. En esto hay un número máximo de bits para ajustar el número y el número se mantiene en forma científica en binario. Aquí 0.07 no se puede representar exactamente y se mantiene como 0.070000000000000011.

Para más ver muchas preguntas sobre SO (aunque en otros idiomas) usando la etiqueta , wikipedia y What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

Impresionante, gracias – Rodders

4

medida que la gente ya se ha explicado, el único tipo numérico utilizado en XPath es xs: dobles.

La función number() convierte un valor en un doble. Por lo tanto, las operaciones con números en XPath 1.0 pueden, y en ocasiones conducen a la pérdida de precisión.

Existen diferentes soluciones:

  1. Use la función round(). También se pueden usar las funciones floor() o ceiling().

  2. Utilice el XSLT format-number() función() o la instrucción <xsl:number>.

tenga en cuenta que XPath 2.0 es compatible con todos los tipos numéricos XSD, incluyendo xs:decimal. Un XPath 2.0 expresión que no causa pérdida de precisión es:

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

Impresionante, gracias – Rodders

+0

@ user1603018, De nada. –

+1

De hecho, en XPath 2.0 el literal numérico 0.07 es un xs: decimal, por lo que el molde a xs: decimal es innecesario. Sin embargo, leer un atributo cuyo valor es "0.07" le da un xs: double, a menos que esté haciendo un proceso con reconocimiento de esquema y el esquema le da el tipo como xs: decimal. –