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
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
,
sí
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.