Agregar comportamiento matemático infinito a Decimal
Frecuentes
Visto 4,017 veces
3
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)
1 Respuestas
6
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 c# generics math infinity or haz tu propia pregunta.
¿Está sugiriendo que esto se agregue a la BCL o está preguntando cómo hacerlo en C#? - Peter Ritchie
@PeterRitchie Está bastante claro que OP está buscando lo último ... - Zong
"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. - Servy
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. - Pauli Price
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. - David Heffernan