Agregar comportamiento matemático infinito a Decimal

C# admite matemáticas infinitas para tipos binarios de punto flotante (Double y Single) (ver: Expresar infinito matemático en C #), pero no para Decimal. me gusta el Decimal type por la precisión que ofrece, pero también necesito soporte para matemáticas infinitas (detalles a continuación).

¿Existe una forma 'perezosa' de crear un InfinityDecimal estructura que agrega soporte para -Inf/+Inf/NaN, al igual que la Nullable estructura genérica agrega soporte para Nullable tipos? ¿Quizás hay algún uso interesante de los atributos que podrían aplicarse? ¿Una biblioteca matemática existente que incluye tal bestia?

De lo contrario, debería crear una clase o estructura con un Decimal value propiedad, e implementar explícitamente cada uno de los métodos públicos de la struct Decimal tipo, devolviendo los resultados del equivalente Decimal operación a menos que un operando sea, o un resultado deba ser, +/-Inf o NaN. ¿Bien?

Operaciones matemáticas infinitas:

+INF + N    = +INF (where –INF < N < INF)
-INF + N    = -INF (where –INF < N < INF)
+INF + +INF = +INF
-INF - +INF = -INF
+INF - +INF = NAN 
+INF * +INF = +INF
+INF * -INF = -INF
-INF * -INF = +INF
+INF / +INF = NAN
-INF / -INF = NAN
-INF / +INF = NAN
+INF / -INF = NAN
+INF / 0    = +INF
-INF / 0    = -INF
+INF / N    = +INF (where 0 < N < INF)

preguntado el 27 de noviembre de 13 a las 18:11

¿Está sugiriendo que esto se agregue a la BCL o está preguntando cómo hacerlo en C#? -

@PeterRitchie Está bastante claro que OP está buscando lo último ... -

"De lo contrario, debería crear una clase o estructura con una propiedad de valor Decimal e implementar explícitamente cada uno de los métodos públicos del tipo struct Decimal" Sí, deberá hacerlo. Será tedioso, pero no particularmente difícil. -

Cómo hacerlo. Idealmente, preferiría que se agregara a la BCL, pero a corto plazo me gustaría ver si puedo llegar allí encontrando una implementación existente o mediante algún atajo razonable. -

Defina su propio tipo que encapsule un valor decimal y una enumeración para indicar si el valor es infinito o el valor decimal. FWIW, decimal no se trata de precisión. Se trata de la representación decimal. Decimal tiene una precisión finita, al igual que el doble. Pero decimal es, bueno, decimal, y double es binario. Así que quizás deberías reconsiderar por qué crees que decimal es tan bueno. -

1 Respuestas

Si miras lo que Double y Single hacen, básicamente reservan un valor para representar infinito positivo y negativo. Este valor es básicamente lo más cercano al infinito positivo y negativo que es razonablemente posible representar en cada tipo. Esto, por inferencia, es 1 dividido por el valor más pequeño que no sea cero (es decir, Epsilon). Por supuesto, Decimal no tiene un Epsilon propiedad. Podría crear su propio valor épsilon creando un valor muy cercano a cero sin ser cero:

var DecimalEpsilon = new decimal(1,0,0,false,27);

Eficazmente 0.000000000000000000000000001m.

Luego podría crear infinito positivo y negativo de la misma manera que lo hacen Single y Double:

var DecimalPositiveInfinity =  1m / DecimalEpislon;
var DecimalNegativeInfinity = -1m / DecimalEpislon;

Desafortunadamente, tendrías que lidiar con lidiar con decimalValue/zeroValue usted mismo y envuelva la excepción DivideByZeroException y devuelva la constante infinita adecuada, lo que realmente significa envolver todas las divisiones. Es probable que lo mismo ocurra con NaN, ya que tampoco es un Decimal concepto (que se modela en Single/Double as PositiveInfinity/PositiveInfinity.

Decimal se agregó para modelar dinero y tener la mayor precisión posible para evitar errores de redondeo y pérdida de dinero :). En el concepto de "dinero", el infinito no tiene mucho sentido. :)

Implementar el resto de lo que quieres es efectivamente comparaciones...

respondido 27 nov., 13:18

No sé si los conceptos de infinito o no-un-número son menos significativos con el dinero que con cualquier otra cosa. Los cálculos cuyos resultados no se pueden representar causarán problemas, ya sea que arrojen excepciones inmediatas o arrojen un valor "centinela". Hay muchos casos en los que es mejor tener un lote de código que se garantiza que se ejecutará como una unidad y luego verificar si algo salió mal, que lidiar con la posibilidad de que una parte del código pueda generar una excepción a la mitad. Las excepciones inmediatas pueden ser más fáciles de solucionar que las diferidas... - Super gato

...pero tener un ThreadStatic la referencia a un contexto de computación que podría habilitar/deshabilitar la captura inmediata de errores o capturar un seguimiento de pila del primer cálculo fuera de los límites haría posible que un sistema haga que ambos estilos de manejo de errores estén disponibles para el código, dependiendo de sus necesidades inmediatas . - Super gato

Espero ver detalles en su respuesta: pedro ritchie

En lugar de usar 1/epsilon para infinito, creo que tendría más sentido usar directamente decimal.MaxValue (que podría ser igual), pero parece una forma más segura de hacerlo. - Guardabosques del código de Jeff Walker

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.