operaciones - C#multiplicación decimal comportamiento extraño
multiplicar textbox c# (2)
Noté un comportamiento extraño al multiplicar valores decimales en C #. Considere las siguientes operaciones de multiplicación:
1.1111111111111111111111111111m * 1m = 1.1111111111111111111111111111 // OK
1.1111111111111111111111111111m * 2m = 2.2222222222222222222222222222 // OK
1.1111111111111111111111111111m * 3m = 3.3333333333333333333333333333 // OK
1.1111111111111111111111111111m * 4m = 4.4444444444444444444444444444 // OK
1.1111111111111111111111111111m * 5m = 5.5555555555555555555555555555 // OK
1.1111111111111111111111111111m * 6m = 6.6666666666666666666666666666 // OK
1.1111111111111111111111111111m * 7m = 7.7777777777777777777777777777 // OK
1.1111111111111111111111111111m * 8m = 8.888888888888888888888888889 // Why not 8.8888888888888888888888888888 ?
1.1111111111111111111111111111m * 9m = 10.000000000000000000000000000 // Why not 9.9999999999999999999999999999 ?
Lo que no puedo entender son los dos últimos casos anteriores. ¿Cómo es eso posible?
Los matemáticos distinguen entre números racionales y los números reales superconjuntos. Las operaciones aritméticas en números racionales están bien definidas y son precisas. La aritmética (usando los operadores de suma, resta, multiplicación y división) en números reales es "precisa" solo en la medida en que los números irracionales se dejan en una forma irracional (simbólica) o posiblemente convertible en algunas expresiones a un número racional . Ejemplo, la raíz cuadrada de dos no tiene representación decimal (ni ninguna otra base racional). Sin embargo, la raíz cuadrada de dos multiplicada por la raíz cuadrada de dos es racional - 2, obviamente.
Las computadoras y los lenguajes que se ejecutan en ellas generalmente implementan solo números racionales, ocultos detrás de nombres como int, long int, float, doble precisión, real (FORTRAN) o algún otro nombre que sugiera números reales. Pero los números racionales incluidos son limitados, a diferencia del conjunto de números racionales cuyo rango es infinito.
Ejemplo trivial: no se encuentra en las computadoras. 1/2 * 1/2 = 1/4 Eso funciona bien si tienes una clase de números Racionales Y el tamaño de los numeradores y denominadores no supera los límites de la aritmética de enteros. entonces (1,2) * (1,2) -> (1,4)
Pero si los números racionales disponibles fueran decimales Y se limitaran a un solo dígito después del decimal (impracticable), pero representativos de la elección hecha al elegir una implementación para aproximar los números racionales (flotante / real, etc.), entonces 1/2 sería perfectamente convertible a 0.5, luego 0.5 + 0.5 sería igual a 1.0, pero 0.5 * 0.5 tendría que ser 0.2 o 0.3!
decimal
almacena 28 o 29 dígitos significativos (96 bits). Básicamente, la mantisa está en el rango - / + 79,228,162,514,264,337,593,543,950,335.
Eso significa hasta aproximadamente 7.9 .... puede obtener 29 dígitos significativos con precisión, pero por encima de eso no puede. Es por eso que tanto el 8 como el 9 salen mal, pero no los valores anteriores. Solo debe confiar en 28 dígitos significativos en general, para evitar situaciones extrañas como esta.
Una vez que reduzca su entrada original a 28 cifras significativas, obtendrá el resultado que espera:
using System;
class Test
{
static void Main()
{
var input = 1.111111111111111111111111111m;
for (int i = 1; i < 10; i++)
{
decimal output = input * (decimal) i;
Console.WriteLine(output);
}
}
}