c# infinity

c# - ¿Cómo representar infinito entero?



infinity (5)

Necesito una forma de representar un número entero que pueda ser infinito. Prefiero no usar un tipo de punto flotante (double.PositiveInfinity) ya que el número nunca puede ser fraccionario y esto podría hacer que la API sea confusa. ¿Cuál es la mejor manera de hacer esto?

Edit: Una idea que no he visto todavía es usar int? con nulo que representa el infinito. ¿Hay alguna buena razón para no hacer esto?


C # tiene un tipo para esto la clase BigInteger es de tamaño ilimitado

http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx

Si desea que la clase tenga una representación de infinito, entonces envuelva a BigInteger en una clase que le dé un indicador de infinito.

Tendrá que redefinir todos los operadores y conversiones estándar para que esto funcione.

Cómo exactamente tener operaciones en el trabajo infinito depende de su dominio.

(Por ejemplo, en algunas formas de matemáticas te gustaría 2 x infinito = infinito y en otras no).

La forma en que se implementan los detalles realmente depende de su problema de dominio y no queda clara en su pregunta.


Otra implementación parcial (veo que Jack fue más rápido):

struct InfinityInt { readonly int Value; InfinityInt(int value, bool allowInfinities) { if (!allowInfinities && (value == int.MinValue || value == int.MaxValue)) throw new ArgumentOutOfRangeException("value"); Value = value; } public InfinityInt(int value) : this(value, false) { } public static InfinityInt PositiveInfinity = new InfinityInt(int.MaxValue, true); public static InfinityInt NegativeInfinity = new InfinityInt(int.MinValue, true); public bool IsAnInfinity { get { return Value == int.MaxValue || Value == int.MinValue; } } public override string ToString() { if (Value == int.MinValue) return double.NegativeInfinity.ToString(); if (Value == int.MaxValue) return double.PositiveInfinity.ToString(); return Value.ToString(); } public static explicit operator int(InfinityInt ii) { if (ii.IsAnInfinity) throw new OverflowException(); return ii.Value; } public static explicit operator double(InfinityInt ii) { if (ii.Value == int.MinValue) return double.NegativeInfinity; if (ii.Value == int.MaxValue) return double.PositiveInfinity; return ii.Value; } public static explicit operator InfinityInt(int i) { return new InfinityInt(i); // can throw } public static explicit operator InfinityInt(double d) { if (double.IsNaN(d)) throw new ArgumentException("NaN not supported", "d"); if (d >= int.MaxValue) return PositiveInfinity; if (d <= int.MinValue) return NegativeInfinity; return new InfinityInt((int)d); } static InfinityInt FromLongSafely(long x) { if (x >= int.MaxValue) return PositiveInfinity; if (x <= int.MinValue) return NegativeInfinity; return new InfinityInt((int)x); } public static InfinityInt operator +(InfinityInt a, InfinityInt b) { if (a.IsAnInfinity || b.IsAnInfinity) { if (!b.IsAnInfinity) return a; if (!a.IsAnInfinity) return b; if (a.Value == b.Value) return a; throw new ArithmeticException("Undefined"); } return FromLongSafely((long)a.Value + (long)b.Value); } public static InfinityInt operator *(InfinityInt a, InfinityInt b) { if (a.IsAnInfinity || b.IsAnInfinity) { if (a.Value == 0 || b.Value == 0) throw new ArithmeticException("Undefined"); return (a.Value > 0) == (b.Value > 0) ? PositiveInfinity : NegativeInfinity; } return FromLongSafely((long)a.Value * (long)b.Value); } // and so on, and so on }


Si no necesita el rango completo de valores enteros, puede usar las constantes int.MaxValue y int.MinValue para representar infinitos.

Sin embargo, si se requiere el rango completo de valores, sugeriría crear una envoltura o simplemente apostar por el doble.


Su API puede usar una convención que int.MaxValue representa un valor infinito positivo e int.MinValue - un infinito negativo.

Pero aún necesita documentarlo en algún lugar y, puede ser que necesite algunas operaciones con su entero infinito:

/// <summary> /// Making int infinity /// ... /// </summary> public static class IntExtension { public const int PositiveInfinity = int.MaxValue; public const int NegativeInfinity = int.MinValue; public static bool IsPositiveInfinity(this int x) { return x == PositiveInfinity; } public static bool IsNegativeInfinity(this int x) { return x == NegativeInfinity; } public static int Operation(this int x, int y) { // ... return PositiveInfinity; } }


Un ejemplo de implementación parcial a lo largo de las líneas de los comentarios de SLaks y otros (comentarios bienvenidos):

Uso:

int x = 4; iint pi = iint.PositiveInfinity; iint ni = iint.NegativeInfinity; Assert.IsTrue(x + pi == iint.PositiveInfinity); Assert.IsTrue(pi + 1 == iint.PositiveInfinity); Assert.IsTrue(pi + (-ni) == iint.PositiveInfinity); Assert.IsTrue((int)((iint)5) == 5);

Implementación:

public struct iint { private readonly int _int; public iint(int value) { if(value == int.MaxValue || value == int.MinValue) throw new InvalidOperationException("min/max value reserved in iint"); _int = value; } public static explicit operator int(iint @this) { if(@this._int == int.MaxValue || @this._int == int.MinValue) throw new InvalidOperationException("cannot implicit convert infinite iint to int"); return @this._int; } public static implicit operator iint(int other) { if(other == int.MaxValue || other == int.MinValue) throw new InvalidOperationException("cannot implicit convert max-value into to iint"); return new iint(other); } public bool IsPositiveInfinity {get { return _int == int.MaxValue; } } public bool IsNegativeInfinity { get { return _int == int.MinValue; } } private iint(bool positive) { if (positive) _int = int.MaxValue; else _int = int.MinValue; } public static readonly iint PositiveInfinity = new iint(true); public static readonly iint NegativeInfinity = new iint(false); public static bool operator ==(iint a, iint b) { return a._int == b._int; } public static bool operator !=(iint a, iint b) { return a._int != b._int; } public static iint operator +(iint a, iint b) { if (a.IsPositiveInfinity && b.IsNegativeInfinity) throw new InvalidOperationException(); if (b.IsPositiveInfinity && a.IsNegativeInfinity) throw new InvalidOperationException(); if (a.IsPositiveInfinity) return PositiveInfinity; if (a.IsNegativeInfinity) return NegativeInfinity; if (b.IsPositiveInfinity) return PositiveInfinity; if (b.IsNegativeInfinity) return NegativeInfinity; return a._int + b._int; } public static iint operator -(iint a, iint b) { if (a.IsPositiveInfinity && b.IsPositiveInfinity) throw new InvalidOperationException(); if (a.IsNegativeInfinity && b.IsNegativeInfinity) throw new InvalidOperationException(); if (a.IsPositiveInfinity) return PositiveInfinity; if (a.IsNegativeInfinity) return NegativeInfinity; if (b.IsPositiveInfinity) return NegativeInfinity; if (b.IsNegativeInfinity) return PositiveInfinity; return a._int - b._int; } public static iint operator -(iint a) { if (a.IsNegativeInfinity) return PositiveInfinity; if (a.IsPositiveInfinity) return NegativeInfinity; return -a; } /* etc... */ /* other operators here */ }