c# .net decimal floating-accuracy

c# - Inexactitud de decimal en.NET



floating-accuracy (4)

Al agregar paréntesis, se asegura de que la división se calcule antes de la multiplicación. Esto parece ser suficiente para afectar el cálculo lo suficiente como para introducir un problema de precisión flotante .

Como las computadoras no pueden producir todos los números posibles, debes asegurarte de tener esto en cuenta en tus cálculos

Ayer, durante la depuración, me sucedió algo extraño y realmente no puedo explicarlo:

Entonces, tal vez no veo lo obvio aquí o no entendí algo sobre decimales en .NET, pero ¿no deberían ser los mismos resultados?


Si bien Decimal tiene una precisión mayor que Double , su principal característica útil es que cada valor coincide con precisión con su representación legible por humanos . Si bien los tipos decimales fijos que están disponibles en algunos idiomas pueden garantizar que ni la suma ni la resta de dos valores de punto fijo de precisión coincidente, ni la multiplicación de un tipo de punto fijo por un entero, causarán un error de redondeo, y mientras " los tipos "grandes decimales" como los que se encuentran en Java pueden garantizar que ninguna multiplicación causará errores de redondeo, los tipos Decimal coma flotante como el que se encuentra en .NET no ofrecen tales garantías, y ningún tipo decimal puede garantizar que las operaciones de división puedan ser completado sin errores de redondeo (Java tiene la opción de lanzar una excepción en caso de que sea necesario redondear).

Si bien aquellos que deciden hacer que Decimal sea ​​un tipo de punto flotante pueden haber intentado que sea utilizable para situaciones que requieren más dígitos a la derecha del punto decimal o más a la izquierda, tipos de punto flotante, ya sea base-10 o base- 2, hacen que los problemas de redondeo sean inevitables para todas las operaciones.


Decimal solo puede almacenar valores exactos que son exactamente representables en decimal dentro de su límite de precisión. Aquí 22/24 = 0.91666666666666666666666 ... que necesita precisión infinita o un tipo racional para almacenar, y ya no es igual a 22/24 después de redondear.

Si primero haces la multiplicación, todos los valores son exactamente representables, de ahí el resultado que ves.


decimal no es un tipo mágico de hacer todas las matemáticas para mí . Sigue siendo un número de coma flotante; la principal diferencia con respecto a float es que es un número decimal de coma flotante, en lugar de binario . Por lo tanto, puede representar fácilmente 0.3 como decimal (es imposible como un número binario finito), pero no tiene una precisión infinita.

Esto hace que funcione mucho más cerca de que un humano haga los mismos cálculos, pero aún debe imaginarse a alguien haciendo cada operación individualmente. Está específicamente diseñado para cálculos financieros, donde no haces el tipo de cosas que haces en matemáticas: simplemente vas paso a paso, redondeando cada resultado de acuerdo con reglas bastante específicas.

De hecho, para muchos casos, el decimal puede funcionar mucho peor que el float (o mejor, el double ). Esto se debe a que el decimal no hace ningún redondeo automático. Hacer lo mismo con el double le da 22 como se esperaba, porque automáticamente se supone que la diferencia no importa, en decimal , es uno de los puntos importantes sobre el decimal . Puede emular esto insertando el manual Math.Round s, por supuesto, pero no tiene mucho sentido.