'------------------------------------------------------------------------------
' BigFloat (20/Oct/07)
' Estructura para trabajar con números grandes con decimales
'
' Estructura basada en BigInt de F#
' Se necesita una referencia a fslib.dll
'
' Se debe configurar para que no haya overflow en números enteros
'
' El espacio de nombres de esta librería es:
' elGuille.Developer.FSharp
'
' ©Guillermo 'guille' Som, 2007
'------------------------------------------------------------------------------
Option Strict On
Imports Microsoft.VisualBasic
Imports System
Imports System.Text
Imports System.Threading
''' <summary>
''' Estructura para manejar números de gran precisoón
''' de coma flotante
''' </summary>
''' <remarks>
''' Iniciado: 20/Oct/2007
''' Revisado: 22/Oct/2007
''' </remarks>
Public Structure BigFloat
Implements IComparable
''' <summary>
''' Para la interfaz IComparable
''' </summary>
''' <param name="obj"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function CompareTo(ByVal obj As Object) As Integer _
Implements System.IComparable.CompareTo
If TypeOf obj Is BigFloat Then
Dim bf As BigFloat = obj.ToString
Return Compare(Me, bf)
Else
'Return String.Compare(Me.ToString, obj.ToString)
Return 0
End If
End Function
''' <summary>
''' El número completo incluida la parte fraccionaria
''' Si el número es 125.55
''' Entero será 12555 y
''' Decimales será 100
''' </summary>
''' <remarks></remarks>
Friend Entero As BigInt
''' <summary>
''' La posición del decimal
''' Si el número es 125.55
''' Entero será 12555 y
''' Decimales será 100
''' </summary>
''' <remarks></remarks>
Friend Decimales As BigInt
''' <summary>
''' Un valor cero para cuando haga falta
''' no tener que estar calculándolo
''' </summary>
''' <remarks></remarks>
Private Shared ReadOnly bigFloatZero As BigFloat
''' <summary>
''' Un valor uno para cuando haga falta
''' no tener que estar calculándolo
''' </summary>
''' <remarks></remarks>
Private Shared ReadOnly bigFloatOne As BigFloat '= BigInt.One
''' <summary>
''' Un valor dos para cuando haga falta
''' no tener que estar calculándolo
''' </summary>
''' <remarks></remarks>
Private Shared ReadOnly bigFloatTwo As BigFloat
''' <summary>
''' Para el separador de decimales
''' </summary>
''' <remarks></remarks>
Private Shared ReadOnly sepDec As String
''' <summary>
''' Constructor compartido
''' se inicia el separador y los valores de 0, 1 y 2
''' </summary>
''' <remarks></remarks>
Shared Sub New()
sepDec = Thread.CurrentThread.CurrentCulture. _
NumberFormat.CurrencyDecimalSeparator
bigFloatZero = New BigFloat(BigInt.Zero)
bigFloatOne = New BigFloat(BigInt.One)
bigFloatTwo = New BigFloat(2)
End Sub
''' <summary>
''' Crea un nuevo objeto a partir de dos BigInt
''' </summary>
''' <param name="ent"></param>
''' <param name="dec"></param>
''' <remarks></remarks>
Public Sub New(ByVal ent As BigInt, ByVal dec As BigInt)
Entero = ent
If dec.IsZero Then
dec = bigFloatOne 'BigInt.One
End If
Decimales = dec
End Sub
''' <summary>
''' Crea un nuevo objeto a partir de un BigInt
''' </summary>
''' <param name="ent"></param>
''' <remarks></remarks>
Public Sub New(ByVal ent As BigInt)
Entero = ent
' Usar BigInt.One y no bigFloatOne
' ya que a este constructor se llama antes de tener el valor
Decimales = BigInt.One
End Sub
' Parse permite crear nuevas instancias a partir de cadenas o enteros
''' <summary>
''' Convierte una cadena en un BigFloat
''' </summary>
''' <param name="s"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Parse(ByVal s As String) As BigFloat
Dim bn1 As BigInt
Dim i As Integer
i = s.IndexOf(sepDec)
If i = -1 Then
Select Case sepDec
Case ","
i = s.IndexOf(".")
Case Else
i = s.IndexOf(",")
End Select
End If
If i > -1 Then
Dim s2 As String = s.Substring(i + 1)
Dim s1 As String = s.Substring(0, i) & s2
bn1 = s1
Dim bn2 As BigInt = "1" & New String("0"c, Len(s2))
Return New BigFloat(bn1, bn2)
End If
bn1 = s
Return New BigFloat(bn1) ', 1)
End Function
''' <summary>
''' Convierte un doble a BigFloat
''' </summary>
''' <param name="n"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Parse(ByVal n As Double) As BigFloat
' Tener en cuenta los valores del exponente
' Por ejemplo:
' 1,23456789012346E+16 es:
' 12345678901234600
' 1,23456789012346E-16 es:
' 0.000000000000000123456789012346
' 1,23456789012346E-17 es:
' 0.0000000000000000123456789012346
' 123.456789012346E-17
' 0.00000000000000123456789012346
' Cuando es positivo el separador suele estar en la segunda posición
Dim s As String = n.ToString
Dim i As Integer = InStr(s, "E")
If i > 0 Then
Dim signo As String = Mid(s, i + 1, 1)
Dim digitos As Integer = CInt(Mid(s, i + 2))
Dim pDec As Integer = InStr(s, sepDec)
Dim sNum As String = Left(s, i - 1).Replace(sepDec, "")
If signo = "-" Then
' En los negativos se pierden los ceros a la izquierda
' después del decimal,
' ya que se guarda como 0000000000000000123456789012346
' con los decimales correspondientes...
' Ya está corregido en el ToString
Dim relleno As String = New String("0"c, digitos - pDec)
s = "0" & sepDec & relleno & sNum
Else
Dim j As Integer = digitos - Len(sNum) + pDec - 1
Dim relleno As String = New String("0"c, j)
s = Left(sNum, pDec - 1) & Mid(sNum, pDec) & relleno
End If
End If
Return Parse(s)
End Function
''' <summary>
''' Convierte un BigInt en BigFloat
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Parse(ByVal num As BigInt) As BigFloat
Return New BigFloat(num)
End Function
''' <summary>
''' Convierte un BigFloat en un BigInt
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function ToBigInt(ByVal num As BigFloat) As BigInt
Dim s As String = num
Dim i As Integer = s.IndexOfAny(",.".ToCharArray)
If i > -1 Then
s = s.Substring(0, i)
End If
Return New BigInt(s)
End Function
''' <summary>
''' Devuelve un BigFloat con valor cero
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property Zero() As BigFloat
Get
'Return New BigFloat(BigInt.Zero)
Return bigFloatZero
End Get
End Property
''' <summary>
''' El valor de PI con 250 decimales
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property PI() As BigFloat
Get
' Valor de la página
' http://centros5.pntic.mec.es/ies.de.bullas/dp/matema/conocer/pi_1500.htm
Dim s As New StringBuilder(260)
s.Append("3.")
s.Append("14159265358979323846264338327950288419716939937510")
s.Append("58209749445923078164062862089986280348253421170679")
s.Append("82148086513282306647093844609550582231725359408128")
s.Append("48111745028410270193852110555964462294895493038196")
s.Append("44288109756659334461284756482337867831652712019091")
' Si añades más decimales, recuerda redondear si es necesario
' aquí tienes hasta el dígito 440 (que puedes usar sin redondear)
' 4564856692 3460348610 4543266482 1339360726 0249141273
' 7245870066 0631558817 4881520920 9628292540 9171536436
' 7892590360 0113305305 4882046652 1384146951 9415116094
' 7363717872 1468440901 2249534301 4654958537
' En realidad habría que devolver solo MaxDecimales
Return Parse(s.ToString)
End Get
End Property
''' <summary>
''' El valor de E con 252 decimales
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property E() As BigFloat
Get
' Valor de la página:
' http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.1mil
Dim s As New StringBuilder(260)
s.Append("2.")
s.Append("71828182845904523536028747135266249775724709369995")
s.Append("95749669676277240766303535475945713821785251664274")
s.Append("27466391932003059921817413596629043572900334295260")
s.Append("59563073813232862794349076323382988075319525101901")
s.Append("15738341879307021540891499348841675092447614606680")
s.Append("82")
' Si añades más decimales, recuerda redondear si es necesario
' aquí tienes hasta el dígito 439 (que puedes usar sin redondear)
' 26480016 8477411853 7423454424 3710753907 7744992069
' 5517027618 3860626133 1384583000 7520449338 2656029760
' 6737113200 7093287091 2744374704 7230696977 2093101416
' 9283681902 5515108657 4637721112 523897844
' En realidad habría que devolver solo MaxDecimales
Return Parse(s.ToString)
End Get
End Property
''' <summary>
''' Devuelve un BigFloat con valor 1
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property One() As BigFloat
Get
'Return New BigFloat(BigInt.One)
Return bigFloatOne
End Get
End Property
''' <summary>
''' Devuelve un BigNum con valor 2
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property Two() As BigFloat
Get
'Return New BigFloat(2)
Return bigFloatTwo
End Get
End Property
''' <summary>
''' Devuelve True si el BigFloat indicado es cero
''' </summary>
''' <param name="n1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function IsZero(ByVal n1 As BigFloat) As Boolean
Return n1.Entero.IsZero 'AndAlso n1.Decimales.IsZero)
End Function
''' <summary>
''' Devuelve True si este número es cero
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function IsZero() As Boolean
Return Entero.IsZero 'AndAlso Decimales.IsZero)
End Function
''' <summary>
''' Convierte el BigFloat indicado en un entero (Int32)
''' </summary>
''' <param name="n1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function ToInt32(ByVal n1 As BigFloat) As Integer
Try
Return n1.Entero.ToInt32
Catch ex As Exception
Console.WriteLine("ERROR: " & ex.Message)
Return 0
End Try
End Function
''' <summary>
''' Convierte este número en un entero (Int32)
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function ToInt32() As Integer
Return BigInt.ToInt32(Me.Entero)
End Function
''' <summary>
''' Devuelve el mayor de la lista indicada
''' </summary>
''' <param name="parametros"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Max(ByVal ParamArray parametros() As BigFloat) As BigFloat
Array.Sort(parametros)
Return parametros(parametros.Length - 1)
End Function
''' <summary>
''' Devuelve el menor de la lista indicada
''' </summary>
''' <param name="parametros"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Min(ByVal ParamArray parametros() As BigFloat) As BigFloat
Array.Sort(parametros)
Return parametros(0)
End Function
''' <summary>
''' Devuelve el resto de la división
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function [Mod](ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Dim bf1 As BigFloat = BigInt.DivMod(bn1.Entero * bn2.Decimales, _
bn2.Entero * bn1.Decimales)
Dim bf2 As BigFloat = bn1.Decimales * bn2.Decimales
Return bf1 / bf2
End Function
''' <summary>
''' Devuelve la suma de todos los valores indicados
''' </summary>
''' <param name="parametros"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Suma(ByVal ParamArray parametros() As BigFloat) As BigFloat
Dim t As BigFloat = parametros(0)
For i As Integer = 1 To parametros.Length - 1
t = t + parametros(i)
Next
Return t
End Function
''' <summary>
''' Suma el contenido de un array con otros valores
''' </summary>
''' <param name="numeros"></param>
''' <param name="parametros"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Suma(ByVal numeros() As BigFloat, _
ByVal ParamArray parametros() As BigFloat) As BigFloat
Dim t As BigFloat = parametros(0)
For i As Integer = 1 To parametros.Length - 1
t = t + parametros(i)
Next
For i As Integer = 0 To numeros.Length - 1
t = t + numeros(i)
Next
Return t
End Function
''' <summary>
''' Devuelve la media aritmética de los números indicados
''' El valor devuelto es de tipo BigFloat
''' </summary>
''' <param name="parametros"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Media(ByVal ParamArray parametros() As BigFloat) As BigFloat
Dim t As BigFloat = Suma(parametros)
Return t \ parametros.Length
End Function
''' <summary>
''' Devuelve la media del total y la cantidad indicadas
''' Esto es válido para calcular primero con Suma
''' </summary>
''' <param name="total"></param>
''' <param name="cant"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Media(ByVal total As BigFloat, ByVal cant As BigFloat) As BigFloat
Return total \ cant
End Function
''' <summary>
''' Devuelve el porcentaje del primero número sobre el segundo:
''' num1 * num2 / 100
''' </summary>
''' <param name="num1"></param>
''' <param name="num2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Porcentaje(ByVal num1 As BigFloat, _
ByVal num2 As BigFloat) As BigFloat
Return num1 * num2 / 100
End Function
''' <summary>
''' Cambia el signo del número indicado
''' </summary>
''' <param name="num1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Neg(ByVal num1 As BigFloat) As BigFloat
num1.Entero = BigInt.Neg(num1.Entero)
Return num1
End Function
''' <summary>
''' Multiplica dos BigFloat
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Mul(ByVal n1 As BigFloat, ByVal n2 As BigFloat) As BigFloat
' 3.1 x 2.5 = 31x25 / 10x10
Dim bn1 As BigInt = BigInt.Mul(n1.Entero, n2.Entero)
Dim bn2 As BigInt = BigInt.Mul(n1.Decimales, n2.Decimales)
Return New BigFloat(bn1, bn2)
End Function
''' <summary>
''' Devuelve el resultado de dividir los dos números
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks>
''' v.0.3 20/Oct/07
''' </remarks>
Public Shared Function Div(ByVal n1 As BigFloat, ByVal n2 As BigFloat) As BigFloat
Dim bn1 As BigInt = BigInt.Mul(n1.Entero, n2.Decimales)
Dim bn2 As BigInt = BigInt.Mul(n2.Entero, n1.Decimales)
Return DivBigIntToFloat(bn1, bn2)
End Function
''' <summary>
''' Devuelve el resto de la división
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function DivMod(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return BigFloat.Mod(bn1, bn2)
End Function
''' <summary>
''' División entera (se redondea)
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function DivInt(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Round(Div(bn1, bn2))
End Function
''' <summary>
''' Número máximo de decimales a mostrar en las fracciones
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Property MaxDecimales() As Integer
Get
Return BigInt.MaxDecimales
End Get
Set(ByVal value As Integer)
BigInt.MaxDecimales = value
End Set
End Property
''' <summary>
''' Divide dos BigInt y devuelve un BigFloat
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function DivBigIntToFloat(ByVal bn1 As BigInt, _
ByVal bn2 As BigInt) As BigFloat
Dim bn3 As BigInt = BigInt.Zero
Dim s4 As String = BigInt.DivFrac(bn1, bn2, bn3)
Dim s3 As String = bn3
Dim bn5 As BigInt = (s3 & s4)
Dim bi As BigInt = ("1" & New String("0"c, Len(s4)))
Return New BigFloat(bn5, bi)
End Function
''' <summary>
''' Suma dos BigFloat
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Add(ByVal n1 As BigFloat, ByVal n2 As BigFloat) As BigFloat
Dim bn1 As BigInt = BigInt.Add(n1.Entero * n2.Decimales, _
n2.Entero * n1.Decimales)
Dim bn2 As BigInt = BigInt.Mul(n1.Decimales, n2.Decimales)
Return DivBigIntToFloat(bn1, bn2)
End Function
''' <summary>
''' Resta los dos BigFloat indicados
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function [Sub](ByVal n1 As BigFloat, ByVal n2 As BigFloat) As BigFloat
Dim bn1 As BigInt = BigInt.Sub(n1.Entero * n2.Decimales, _
n2.Entero * n1.Decimales)
Dim bn2 As BigInt = BigInt.Mul(n1.Decimales, n2.Decimales)
Return DivBigIntToFloat(bn1, bn2)
End Function
''' <summary>
''' Decrementa uno al BigFloat indicado
''' </summary>
''' <param name="n1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Dec(ByVal n1 As BigFloat) As BigFloat
Return BigFloat.Sub(n1, BigFloat.One)
End Function
''' <summary>
''' Decrementa el primer BigFloat por la cantidad del segundo
''' (es como restarlos, en realidad es lo mismo que Sub)
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Dec(ByVal n1 As BigFloat, ByVal n2 As BigFloat) As BigFloat
Return BigFloat.Sub(n1, n2)
End Function
''' <summary>
''' Incrementa en uno el BigFloat indicado
''' </summary>
''' <param name="n1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Inc(ByVal n1 As BigFloat) As BigFloat
Return BigFloat.Add(n1, BigFloat.One)
End Function
''' <summary>
''' Incrementa el primer BigFloat con el segundo
''' Es como sumarlos
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Inc(ByVal n1 As BigFloat, ByVal n2 As BigFloat) As BigFloat
Return BigFloat.Add(n1, n2)
End Function
''' <summary>
''' Comprueba si los dos números son iguales
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Iguales(ByVal n1 As BigFloat, _
ByVal n2 As BigFloat) As Boolean
If n1.Entero = n2.Entero AndAlso n1.Decimales = n2.Decimales Then
Return True
Else
Return False
End If
End Function
''' <summary>
''' Devuelve True si los dos números son iguales
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Equal(ByVal n1 As BigFloat, _
ByVal n2 As BigFloat) As Boolean
Return Iguales(n1, n2)
End Function
''' <summary>
''' Compara dos valores
''' Devuelve 0 si son iguales
''' -1 si el primero es menor
''' 1 si el primero es mayor
''' </summary>
''' <param name="n1"></param>
''' <param name="n2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Compare(ByVal n1 As BigFloat, _
ByVal n2 As BigFloat) As Integer
Dim bfr1 As BigFrac = n1
Dim bfr2 As BigFrac = n2
Return BigFrac.Compare(bfr1, bfr2)
End Function
''' <summary>
''' Redondea el número al siguiente entero
''' si la fracción es superior a 0.5
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Round(ByVal num As BigFloat) As BigFloat
num = num + 0.5
Dim s As String = num
Dim i As Integer = s.IndexOfAny(",.".ToCharArray)
If i > -1 Then
s = s.Substring(0, i)
End If
Return New BigFloat(s)
End Function
''' <summary>
''' Redondea al siguiente número usando los decimales indicados
''' </summary>
''' <param name="num"></param>
''' <param name="decimales"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Round(ByVal num As BigFloat, _
ByVal decimales As BigFloat) As BigFloat
Dim j As Integer = CInt(decimales)
If j < 1 Then Return num
Dim s As String = num
Dim i As Integer = s.IndexOfAny(",.".ToCharArray)
If i = -1 Then
Return num
End If
Dim decim As String = s.Substring(i + 1)
If j > Len(decim) Then
Return num
End If
Dim n2 As String = "1" & New String("0"c, Len(decim) - j)
Dim bf As BigFloat = Parse(decim) / Parse(n2) + 0.5
Dim bi As BigInt = bf
Dim s1 As String = bi.ToString
s = s.Substring(0, i) & sepDec & s1
' No devolver con New que se convierte a BigInt
Return Parse(s) ' New BigFloat(s)
End Function
''' <summary>
''' Eleva el primer número a la potencia del segundo
''' (no funciona bien con potencias decimales)
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Pow(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Dim d2 As Double = CDbl(bn2)
Return New BigFloat(BigInt.Pow(bn1.Entero, d2), BigInt.Pow(bn1.Decimales, d2))
End Function
'
' Métodos que usan Double para hacer los cálculos
' Todas o casi las funciones de System.Math
' (hasta que encuentre la forma de hacerlo con este tipo de datos)
'
' Aunque no estén por orden alfabético, al principio
' pongo los métodos que usan el tipo de forma adecuda
' y después están los métodos que usan la clase System.Math
' y que por tanto solo tienen la precisión de Double.
'
' También hay otros métodos que no están en System.Math
'
''' <summary>
''' Devuelve el valor absoluto (positivo) del número
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Abs(ByVal num As BigFloat) As BigFloat
If num < BigFloat.Zero Then
Return (num * -BigFloat.One)
Else
Return num
End If
End Function
''' <summary>
''' Devuelve el siguiente número entero
''' Si es negativo se devuelve el mismo sin decimales
''' Si es positivo se devuelve el siguiente
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Ceiling(ByVal num As BigFloat) As BigFloat
If num.IsZero Then
Return num
ElseIf num > BigFloat.Zero Then
Return Truncate(num + BigFloat.One)
Else
Return Truncate(num)
End If
End Function
''' <summary>
''' Devuelve el entero anterior
''' Si es positivo devuelve el mismo número sin decimales
''' Si es negativo devuelve el número menos 1
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Floor(ByVal num As BigFloat) As BigFloat
If num.IsZero Then
Return num
ElseIf num > BigFloat.Zero Then
Return Truncate(num)
Else
Return Truncate(num - BigFloat.One)
End If
End Function
''' <summary>
''' Devuelve el signo del número
''' 0 si es cero
''' 1 si es positivo
''' -1 si es negativo
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Sign(ByVal num As BigFloat) As Integer
If num.IsZero Then
Return 0
ElseIf num > BigFloat.Zero Then
Return 1
Else
Return -1
End If
End Function
''' <summary>
''' Devuelve True si el número es negativo
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Negative(ByVal num As BigFloat) As Boolean
Return Sign(num) = -1
End Function
''' <summary>
''' Devuelve True si el número es positivo
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Positive(ByVal num As BigFloat) As Boolean
Return Sign(num) = 1
End Function
''' <summary>
''' Devuelve el número sin decimales
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Truncate(ByVal num As BigFloat) As BigFloat
Dim bi As BigInt = BigFloat.ToBigInt(num)
Return Parse(bi)
End Function
''' <summary>
''' Devuelve el número sin decimales
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Fix(ByVal num As BigFloat) As BigFloat
Return Truncate(num)
End Function
Public Shared Function Acos(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Acos(CDbl(num)))
End Function
Public Shared Function Asin(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Asin(CDbl(num)))
End Function
Public Shared Function Atan(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Atan(CDbl(num)))
End Function
Public Shared Function Atan2(ByVal num1 As BigFloat, _
ByVal num2 As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Atan2(CDbl(num1), CDbl(num2)))
End Function
Public Shared Function Cos(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Cos(CDbl(num)))
End Function
Public Shared Function Cosh(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Cosh(CDbl(num)))
End Function
Public Shared Function Exp(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Exp(CDbl(num)))
End Function
Public Shared Function Log(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Log(CDbl(num)))
End Function
Public Shared Function Log(ByVal num As BigFloat, _
ByVal newBase As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Log(CDbl(num), CDbl(newBase)))
End Function
Public Shared Function Log10(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Log10(CDbl(num)))
End Function
Public Shared Function Sin(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Sin(CDbl(num)))
End Function
Public Shared Function Sinh(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Sinh(CDbl(num)))
End Function
''' <summary>
''' La raíz cuadrada de un número
''' El valor máximo es el de un Double
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Sqrt(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Sqrt(CDbl(num)))
End Function
Public Shared Function Tan(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Tan(CDbl(num)))
End Function
Public Shared Function Tanh(ByVal num As BigFloat) As BigFloat
Return BigFloat.Parse(System.Math.Tanh(CDbl(num)))
End Function
'--------------------------------------------------------------------------
' Métodos de instancia
' Si hay métodos de instancia y compartidos que se llaman igual
' estarán definidos con los compartidos.
'--------------------------------------------------------------------------
''' <summary>
''' Devuelve una cadena con el BigNum actual
''' </summary>
''' <returns></returns>
''' <remarks>
''' v.0.2 19/Oct/07
''' Si la parte decimal es cero, no se muestra
''' v.0.6 20/Oct/07
''' Si la parte entera es cero, mostrar el cero
''' </remarks>
Public Overrides Function ToString() As String
Dim i As Integer = Me.Decimales.ToString.Length - 1
' Si no tiene decimales
' devolver todo el número
If i < 1 Then
i = 1
Me.Decimales = 10
Me.Entero = Me.Entero * 10
End If
Dim s As String = Me.Entero.ToString
Dim j As Integer = Len(s) - i
' Falla con la conversión de Double a BigFloat
' ya que los valores exponenciales no los controla bien
' Aunque con esto y con lo que hago en el Parse...
' parece que está bien
If j < 0 Then
j = i - Len(s) + 1
s = New String("0"c, j) & s
j = 0
End If
Dim bn As BigInt = Mid(s, j + 1)
If bn.IsZero Then
If j = 0 Then
Return "0"
End If
Return Left(s, j)
End If
If j = 0 Then
Return "0" & sepDec & Mid(s, j + 1)
End If
Return Left(s, j) & sepDec & Mid(s, j + 1)
End Function
'--------------------------------------------------------------------------
' Sobrecarga de operadores y conversiones
'--------------------------------------------------------------------------
'
' Conversiones
'
''' <summary>
''' Convierte un Double en un BigFloat
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Widening Operator CType(ByVal num As Double) As BigFloat
Return Parse(num)
End Operator
''' <summary>
''' Convierte un BigFloat en un Double
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Narrowing Operator CType(ByVal num As BigFloat) As Double
Return CDbl(num.ToString)
End Operator
''' <summary>
''' Convierte un BigFloat en un Int32 (Integer)
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Narrowing Operator CType(ByVal num As BigFloat) As Integer
Return ToInt32(num)
End Operator
''' <summary>
''' Convierte un BigFloat en una cadena
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Widening Operator CType(ByVal num As BigFloat) As String
' Se devuelve lo mismo que ToString
' ya que se hace la comprobación de si se debe mostrar el decimal
Return num.ToString
End Operator
''' <summary>
''' Convierte una cadena en un BigFloat
''' La cadena solo debe contener números
''' Se admite indistintamente la coma o el punto
''' como separador decimal
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Widening Operator CType(ByVal num As String) As BigFloat
Return Parse(num)
End Operator
''' <summary>
''' Convierte un BigInt en un BigFloat
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Widening Operator CType(ByVal num As BigInt) As BigFloat
Return Parse(num)
End Operator
''' <summary>
''' Convierte un BigFloat en un BigInt
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Widening Operator CType(ByVal num As BigFloat) As BigInt
Return ToBigInt(num)
End Operator
'
' Sobrecarga de operadores
'
''' <summary>
''' Operador + unario, devuelve el mismo número
''' </summary>
''' <param name="bn1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator +(ByVal bn1 As BigFloat) As BigFloat
Return bn1
End Operator
''' <summary>
''' Operador unario, niega el número
''' Si es positivo devuelve uno negativo
''' si es negativo lo devuelve como positivo
''' </summary>
''' <param name="bn1"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator -(ByVal bn1 As BigFloat) As BigFloat
Return BigFloat.Neg(bn1)
End Operator
''' <summary>
''' Suma dos valores
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator +(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Add(bn1, bn2)
End Operator
''' <summary>
''' Resta dos valores
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator -(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return [Sub](bn1, bn2)
End Operator
''' <summary>
''' Multiplica dos valores
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator *(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Mul(bn1, bn2)
End Operator
''' <summary>
''' Divide dos valores
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator /(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Div(bn1, bn2)
End Operator
''' <summary>
''' División entera
''' Devuelve la parte entera de dividir los dos valores
''' después de redondearlo
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator \(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Round(Div(bn1, bn2))
End Operator
''' <summary>
''' Eleva el primer número a la potencia del segundo
''' (no funciona bien con potencias decimales)
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator ^(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Pow(bn1, bn2)
End Operator
''' <summary>
''' Devuelve el resto de la división
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator Mod(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return BigFloat.Mod(bn1, bn2)
End Operator
''' <summary>
''' Devuelve True si son iguales
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator =(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Return Iguales(bn1, bn2)
End Operator
''' <summary>
''' Devuelve True si son distintos
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator <>(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Return Not Iguales(bn1, bn2)
End Operator
''' <summary>
''' Devuelve True si el primero es menor
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator <(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Dim i As Integer = Compare(bn1, bn2)
Return i = -1
End Operator
''' <summary>
''' Devuelve True si el primero es mayor
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator >(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Dim i As Integer = Compare(bn1, bn2)
Return i = 1
End Operator
''' <summary>
''' Devuelve True si el primero es menor o igual
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator <=(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Dim i As Integer = Compare(bn1, bn2)
Return i <= 0
End Operator
''' <summary>
''' Devuelve True si el primero es mayor o igual
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator >=(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Dim i As Integer = Compare(bn1, bn2)
Return i >= 0
End Operator
''' <summary>
''' Devuelve True si el número no es cero
''' </summary>
''' <param name="bn"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator IsTrue(ByVal bn As BigFloat) As Boolean
Return Not IsZero(bn)
End Operator
''' <summary>
''' Devuelve True si el número es cero
''' </summary>
''' <param name="bn"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Operator IsFalse(ByVal bn As BigFloat) As Boolean
Return IsZero(bn)
End Operator
End Structure