'------------------------------------------------------------------------------
' BigFloat (12/Oct/07)
' Estructura para trabajar con números grandes con decimales
'
' Basado en BigNum
' Estructura para trabajar con números enteros de alta precisión.
'
' La DLL BigNum_ltm.dll debe estar en el mismo directorio o en el PATH.
'
' ©Guillermo 'guille' Som, 2006-2007
'
' Para usar esta estructura
' Dim a As BigFloat
' a = BigFloat.Parse("...")
'------------------------------------------------------------------------------
Option Explicit On
Option Strict On
Imports System
Imports Microsoft.VisualBasic
Imports System.Text
Imports System.Threading
''' <summary>
''' Estructura para manejar números de gran preción de coma flotante
''' </summary>
''' <remarks>
''' Iniciado: 12/Oct/2007
''' Revisado: 22/Oct/2007
''' </remarks>
Public Structure BigFloat
Implements IComparable
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
Public Entero As BigNum
Public Decimales As BigNum
Private Shared ReadOnly bigFloatZero As BigFloat
Private Shared ReadOnly bigFloatOne As BigFloat
Private Shared ReadOnly bigFloatTwo As BigFloat
Private Shared ReadOnly sepDec As String
Shared Sub New()
sepDec = Thread.CurrentThread.CurrentCulture. _
NumberFormat.CurrencyDecimalSeparator
bigFloatZero = New BigFloat(BigNum.Zero)
bigFloatOne = New BigFloat(BigNum.One)
bigFloatTwo = New BigFloat(BigNum.Two)
End Sub
Public Sub New(ByVal ent As BigNum, ByVal dec As BigNum)
Entero = ent
If dec.IsZero Then
dec = bigFloatOne ' BigNum.One
End If
Decimales = dec
End Sub
Public Sub New(ByVal ent As BigNum)
Entero = ent
' Hay que usr BigNum.One porque el valor
' no se habrá asignado en el constructor
' compartido la primera vez que se llame
' a este constuctor
Decimales = BigNum.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 BigNum
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 BigNum = "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 BigNum en BigFloat
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Parse(ByVal num As BigNum) As BigFloat
Return New BigFloat(num)
End Function
''' <summary>
''' Convierte un BigFloat en un BigNum
''' </summary>
''' <param name="num"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function ToBigNum(ByVal num As BigFloat) As BigNum
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 BigNum(s)
End Function
''' <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 cero
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Zero() As BigFloat
'Return New BigFloat(BigNum.BigNumZero)
Return bigFloatZero
End Function
''' <summary>
''' Devuelve un BigFloat con valor 1
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function One() As BigFloat
'Return New BigFloat(1)
Return bigFloatOne
End Function
''' <summary>
''' Devuelve un BigNum con valor 2
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function Two() As BigFloat
'Return New BigFloat(2)
Return bigFloatTwo
End Function
''' <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.used = 0 'AndAlso n1.Decimales.used = 0)
End Function
''' <summary>
''' Devuelve True si este número es cero
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function IsZero() As Boolean
Return Entero.used = 0 'AndAlso Decimales.used = 0)
End Function
''' <summary>
''' Convierte el BigNum 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 BigNum.ToInt32(Me.Entero)
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 BigNum = BigNum.BigNumMul(n1.Entero, n2.Entero)
Dim bn2 As BigNum = BigNum.BigNumMul(n1.Decimales, n2.Decimales)
Return New BigFloat(bn1, bn2)
End Function
Public Const MaxDecimalesMaxValue As Integer = 1000
Public Const MaxDecimalesMinValue As Integer = 0
Private Shared m_MaxDecimales As Integer = 30
''' <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 m_MaxDecimales
End Get
Set(ByVal value As Integer)
If value < MaxDecimalesMinValue Then
m_MaxDecimales = MaxDecimalesMinValue
ElseIf value > MaxDecimalesMaxValue Then
m_MaxDecimales = MaxDecimalesMaxValue
Else
m_MaxDecimales = value
End If
End Set
End Property
''' <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 BigNum = BigNum.BigNumMul(n1.Entero, n2.Decimales)
Dim bn2 As BigNum = BigNum.BigNumMul(n2.Entero, n1.Decimales)
Return DivBigNumToFloat(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>
''' Divide dos BigNum y devuelve el resultado como BigFloat
''' </summary>
''' <param name="bn1"></param>
''' <param name="bn2"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function DivBigNumToFloat(ByVal bn1 As BigNum, _
ByVal bn2 As BigNum) As BigFloat
Dim bn3 As BigNum = BigNum.Zero
Dim bn4 As BigNum = BigNum.BigNumDiv(bn1, bn2, bn3)
Dim s3 As String = bn3
Dim sb As New System.Text.StringBuilder
Dim n3 As BigNum = BigNum.Zero
For j As Integer = 1 To MaxDecimales
bn1 = bn4 * 10
bn4 = BigNum.BigNumDiv(bn1, bn2, n3)
sb.Append(BigNum.BigNumAbs(n3).ToString)
Next
Dim s4 As String = sb.ToString().TrimEnd("0".ToCharArray)
Dim bn5 As BigNum = (s3 & s4)
Dim bi As BigNum = ("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 BigNum = BigNum.BigNumAdd(n1.Entero * n2.Decimales, _
n2.Entero * n1.Decimales)
Dim bn2 As BigNum = BigNum.Mul(n1.Decimales, n2.Decimales)
Return DivBigNumToFloat(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 BigNum = BigNum.BigNumSub(n1.Entero * n2.Decimales, _
n2.Entero * n1.Decimales)
Dim bn2 As BigNum = BigNum.Mul(n1.Decimales, n2.Decimales)
Return DivBigNumToFloat(bn1, bn2)
End Function
''' <summary>
''' Decrementa uno al BigNum 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 BigNum = 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(System.Math.Pow(CDbl(bn1.Entero), d2), _
System.Math.Pow(CDbl(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)
'
''' <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
'Return BigFloat.Parse(System.Math.Abs(CDbl(num)))
If num < BigFloat.Zero Then
Return (num * -BigFloat.One)
Else
Return num
End If
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
''' <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
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
''' <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
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
''' <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
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
''' <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 BigNum = BigFloat.ToBigNum(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
'--------------------------------------------------------------------------
' 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 BigNum = 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
''' <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 = BigNum.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 entero BigInt
''' </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
Public Shared Function Neg(ByVal num1 As BigFloat) As BigFloat
num1.Entero = BigNum.BigNumNeg(num1.Entero)
Return num1
End Function
'--------------------------------------------------------------------------
' Sobrecarga de operadores
'--------------------------------------------------------------------------
Public Shared Widening Operator CType(ByVal num As Double) As BigFloat
Return Parse(num)
End Operator
Public Shared Narrowing Operator CType(ByVal num As BigFloat) As Double
Return CDbl(num.ToString)
End Operator
Public Shared Narrowing Operator CType(ByVal num As BigFloat) As Integer
Return ToInt32(num)
End Operator
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
Public Shared Widening Operator CType(ByVal num As String) As BigFloat
Return Parse(num)
End Operator
Public Shared Widening Operator CType(ByVal num As BigNum) As BigFloat
Return Parse(num)
End Operator
Public Shared Widening Operator CType(ByVal num As BigFloat) As BigNum
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 BigNum(s)
End Operator
Public Shared Operator +(ByVal bn1 As BigFloat) As BigFloat
Return bn1
End Operator
Public Shared Operator -(ByVal bn1 As BigFloat) As BigFloat
Return BigFloat.Neg(bn1)
End Operator
Public Shared Operator +(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Add(bn1, bn2)
End Operator
Public Shared Operator -(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return [Sub](bn1, bn2)
End Operator
Public Shared Operator *(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Mul(bn1, bn2)
End Operator
Public Shared Operator /(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Div(bn1, bn2)
End Operator
Public Shared Operator \(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As BigFloat
Return Div(bn1, bn2)
End Operator
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
Public Shared Operator =(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Return Iguales(bn1, bn2)
End Operator
Public Shared Operator <>(ByVal bn1 As BigFloat, ByVal bn2 As BigFloat) As Boolean
Return Not Iguales(bn1, bn2)
End Operator
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
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
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
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
Public Shared Operator IsTrue(ByVal bn As BigFloat) As Boolean
Return Not IsZero(bn)
End Operator
Public Shared Operator IsFalse(ByVal bn As BigFloat) As Boolean
Return IsZero(bn)
End Operator
End Structure