Operar con números grandes
|
|
Novedades en la revisión 0.1:
Bueno, pues esto ya parece otra cosa... o casi...
Estas son las nuevas cosas de esta revisión:
-Ahora está en una clase (o estructura) llamada Real con los métodos estáticos (compartidos)
-Se pueden realizar divisiones.
-Se admiten operaciones con decimales (fracciones)
-Se puede indicar el número máximo de decimales (incluso cero) por medio de NumDecimales (valor predeterminado = 4)
-En las divisiones se puede indicar que se muestre el resto (MostrarResto = True)
Novedades en la revisión 0.2 (sólo en C#):
La revisión 0.2 es la versión de C# con sobrecarga de operadores, conversiones de tipos y otras cosillas, como la de comprobar si un número es menor que otro... que aunque parezca fácil, no lo es tanto, ya que al ser cadenas de caracteres las comparaciones no funcionan igual que en los números.
En el código de C# he creado una estructura, que además de tener los métodos (funciones) de la versión "normal" he añadido ciertas sobrecargas como la de la suma (+), la resta (-), la multiplicación (*) y la división (/), no he sobrecargado la exponenciación porque C# no tiene...
También he creado las siguientes conversiones:
-De Real a String
-De String a Real
-De Real a int (explícita, hay que hacer cast)
-De long a Real (y por extensión cualquier tipo inferior, int, etc.)
-De decimal a Real
-De double a Real (y también float)
-Los operadores booleanos <, >, == y !=Para usarlo se haría algo así:
Real r1;
r1 = "123456";
r1.Valor = "123456";
Real r2 = new Real("952145.50");
Console.WriteLine( r1 * r2);Pero esta librería sólo se puede usar en C# (al menos para poder usar las sobrecargas)
Si se quiere usar con Visual Basic habrá que usar los métodos equivalentes a los operadores sobrecargados:
* op_Multiply
/ op_Division
+ op_Addition
- op_Substraction
== op_Equality
!= op_Inequality
< op_LessThan
> op_GreaterThanAdemás de las conversiones (implícitas o explícitas):
op_Implicit
op_Explicit (sólo la que convierte de Real a Integer)
La verdad es que esto de las sobrecargas de C# me tenían engañado... siempre había pensado que también se podrían usar en Visual Basic de la misma forma que en C#. En fin... habrá que esperar a la versión 2005 para que se puedan usar las sobrecargas de forma indistinta, es decir, sin que importe con que lenguaje se ha escrito y con cual se utiliza.
El código mostrado de Visual Basic es el "casi" equivalente a C#, pero sin las sobrecargas.
El código mostrado de C# es el que incluye las sobrecargas de operadores y conversiones.Nos vemos.
Guillermo
P.S.
Si alguien se anima a colaborar en este proyecto... podríamos hacer algo realmente útil.
'------------------------------------------------------------------------------ ' Multiplicar números usando cadenas de caracteres (10/Ago/04) ' ' Realizar operaciones con números de cualquier longitud ' Admite decimales (11/Ago/04) ' ' Operaciones soportadas: ' Multiplicación, División, Potencia, Suma y Resta ' ' ©Guillermo 'guille' Som, 2004 '------------------------------------------------------------------------------ Option Explicit On Option Strict On Imports System Namespace elGuille.Math Public Class Real Friend Shared ad() As String Public Shared NumDecimales As Integer = 4 Public Shared MostrarResto As Boolean = False ' ' Private Shared Function miDiv2(ByVal num1 As String, ByVal num2 As String, ByVal decAct As Integer) As String Dim res As String = num1 Dim n As Integer = 0 If num2.Length < num1.Length Then num2 = (New String("0"c, num1.Length) & num2).Substring(num2.Length, num1.Length) End If Do res = miResta2(res, num2) n += 1 If res = "0" OrElse res < num2 Then Exit Do Loop res = quitarCeros(res) If res <> "0" Then If decAct < NumDecimales Then decAct += 1 res = miDiv2(res & "0", num2, decAct) ' quitar los puntos que haya res = res.Replace(".", "") Return n.ToString & "." & res Else ' si queda un resto mostrarlo con : ' (o bien no mostrarlo) If MostrarResto Then Return n.ToString & ":" & res Else Return n.ToString '& ":" & res End If End If Else Return n.ToString End If End Function Public Shared Function Div2(ByVal num1 As String, ByVal num2 As String) As String ' Para dividir dos números: ' Se leva restando al dividendo el divisor hasta que ' el resto sea cero o menor que el divisor Dim decAct As Integer = 0 ' Dim nDec1 As Integer Dim nDec2 As Integer Dim dec1 As Integer = num1.IndexOf(".") Dim dec2 As Integer = num2.IndexOf(".") If dec1 > -1 Then num1 = quitarCerosFinales(num1) nDec1 = num1.Substring(dec1 + 1).Length num1 = num1.Replace(".", "") End If If dec2 > -1 Then num2 = quitarCerosFinales(num2) nDec2 = num2.Substring(dec2 + 1).Length num2 = num2.Replace(".", "") End If If nDec1 > 0 Then num2 = num2 & New String("0"c, nDec1) End If If nDec2 > 0 Then num1 = num1 & New String("0"c, nDec2) End If ' Return miDiv2(num1, num2, decAct) End Function ' Public Shared Function PotN(ByVal num1 As String, ByVal elevado As String) As String Dim i As Integer ' ' si el exponente tiene decimales, quitárselo i = elevado.IndexOf(".") If i > -1 Then elevado = elevado.Substring(0, i) End If ' If elevado = "0" Then Return "1" ElseIf elevado = "1" Then Return num1 End If If num1 = "1" Then Return "1" ElseIf num1 = "0" Then Return "0" End If ' i = CInt(elevado) - 1 Dim p(i) As String For k As Integer = 0 To i p(k) = num1 Next Return Mult2(p) End Function ' Public Shared Function Mult2(ByVal ParamArray nums() As String) As String Dim total As String = nums(0) For i As Integer = 1 To nums.Length - 1 Dim n1 As String = nums(i) total = Mult2(total, n1) Next ' Return total End Function Public Shared Function Mult2(ByVal num1 As String, ByVal num2 As String) As String ' ' Comprobar si alguno de los números tiene decimales (11/Ago/04) Dim nDec As Integer ' Dim dec1 As Integer = num1.IndexOf(".") Dim dec2 As Integer = num2.IndexOf(".") If dec1 > -1 Then nDec = num1.Substring(dec1 + 1).Length num1 = num1.Replace(".", "") End If If dec2 > -1 Then nDec += num2.Substring(dec2 + 1).Length num2 = num2.Replace(".", "") End If ' ' Poner el más largo como primer número If num2.Length > num1.Length Then Swap(num1, num2) End If ' ' El número de operaciones necesarias ' será la cantidad de cifras del más pequeño ReDim ad(num2.Length - 1) Dim n As Integer = -1 Dim resto As String = "0" Dim res As String = "" ' ' Multiplicar formando filas con los resultados (al estilo manual) For i As Integer = num2.Length - 1 To 0 Step -1 n += 1 ad(n) = "" ' Añadir espacios a la derecha según la cifra (fila) que se procese For k As Integer = 1 To n ad(n) &= " " Next Dim c1 As String = num2.Substring(i, 1) ' Para simplificar las cosas ' se comprueba si se multiplicará por ceo o por uno ' de forma que no sea necesario hacer estas operaciones If c1 = "0" Then ad(n) = New String("0"c, num1.Length) & ad(n) ElseIf c1 = "1" Then ad(n) = num1 & ad(n) Else For j As Integer = num1.Length - 1 To 0 Step -1 Dim c2 As String = num1.Substring(j, 1) res = (CInt("0" & c1) * CInt("0" & c2) + CInt(resto)).ToString 'ad(n) = vb.Right(res, 1) & ad(n) ad(n) = res.Substring(res.Length - 1, 1) & ad(n) If res.Length - 1 < 1 Then resto = "0" Else resto = res.Substring(0, res.Length - 1) End If Next If resto <> "0" Then ad(n) = resto & ad(n) resto = "0" End If End If Next ' res = sumarFilas() If nDec > 0 Then If NumDecimales = 0 Then res = res.Substring(0, res.Length - nDec) Else resto = res.Substring(res.Length - nDec) If resto.Length > NumDecimales Then resto = resto.Substring(0, NumDecimales) End If res = res.Substring(0, res.Length - nDec) & "." & quitarCerosFinales(resto) End If End If Return res End Function ' Public Shared Function Suma2(ByVal ParamArray nums() As String) As String ' ReDim ad(nums.Length - 1) For i As Integer = 0 To nums.Length - 1 ad(i) = nums(i) Next ' Return sumarFilas() End Function Public Shared Function Suma2(ByVal num1 As String, ByVal num2 As String) As String ReDim ad(1) ' Dim nDec As Integer Dim nDec1 As Integer Dim nDec2 As Integer Dim dec1 As Integer = num1.IndexOf(".") Dim dec2 As Integer = num2.IndexOf(".") If dec1 > -1 Then num1 = quitarCerosFinales(num1) nDec1 = num1.Substring(dec1 + 1).Length num1 = num1.Replace(".", "") End If If dec2 > -1 Then num2 = quitarCerosFinales(num2) nDec2 = num2.Substring(dec2 + 1).Length num2 = num2.Replace(".", "") End If If nDec1 > 0 Then num2 = num2 & New String("0"c, nDec1) End If If nDec2 > 0 Then num1 = num1 & New String("0"c, nDec2) End If nDec = nDec1 + nDec2 ' ad(0) = num1 ad(1) = num2 ' 'Return sumarFilas() ' Dim res As String = sumarFilas() Dim resto As String = "" If nDec > 0 Then If NumDecimales = 0 Then res = res.Substring(0, res.Length - nDec) Else resto = res.Substring(res.Length - nDec) If resto.Length > NumDecimales Then resto = resto.Substring(0, NumDecimales) End If res = res.Substring(0, res.Length - nDec) & "." & quitarCerosFinales(resto) End If End If Return res End Function ' Public Shared Function Resta2(ByVal ParamArray nums() As String) As String Dim total As String = nums(0) For i As Integer = 1 To nums.Length - 1 Dim n1 As String = nums(i) total = miResta2(total, n1) Next ' Return total End Function Private Shared Function miResta2(ByVal num1 As String, ByVal num2 As String) As String ' usar esta función para cálculos internos en los que no se deben quitar ' los ceros del principio del número ReDim ad(1) ' Dim nDec As Integer Dim nDec1 As Integer Dim nDec2 As Integer Dim dec1 As Integer = num1.IndexOf(".") Dim dec2 As Integer = num2.IndexOf(".") If dec1 > -1 Then num1 = quitarCerosFinales(num1) nDec1 = num1.Substring(dec1 + 1).Length num1 = num1.Replace(".", "") End If If dec2 > -1 Then num2 = quitarCerosFinales(num2) nDec2 = num2.Substring(dec2 + 1).Length num2 = num2.Replace(".", "") End If If nDec1 > 0 Then num2 = num2 & New String("0"c, nDec1) End If If nDec2 > 0 Then num1 = num1 & New String("0"c, nDec2) End If nDec = nDec1 + nDec2 ' ad(0) = num1 ad(1) = num2 ' 'Return restar2Filas() ' Dim res As String = restar2Filas() Dim resto As String = "" If nDec > 0 Then If NumDecimales = 0 Then res = res.Substring(0, res.Length - nDec) Else resto = res.Substring(res.Length - nDec) If resto.Length > NumDecimales Then resto = resto.Substring(0, NumDecimales) End If res = res.Substring(0, res.Length - nDec) & "." & quitarCerosFinales(resto) End If End If Return res End Function Public Shared Function Resta2(ByVal num1 As String, ByVal num2 As String) As String Return quitarCeros(miResta2(num1, num2)) End Function ' Private Shared Function sumarFilas() As String Dim m As Integer = 0 Dim n As Integer = ad.Length - 1 ' ' m será el número de mayor longitud For k As Integer = 0 To n If ad(k).Length > m Then m = ad(k).Length Next ' ' sumar las filas obtenidas Dim resto As String = "0" Dim total As String = "" Dim res As String = "" ' For k As Integer = 0 To n 'ad(k) = vb.Right(New String(" "c, m) & ad(k), m) ad(k) = (New String(" "c, m) & ad(k)).Substring(ad(k).Length, m) Next For k As Integer = m - 1 To 0 Step -1 res = resto For i As Integer = 0 To n res = (CInt(res) + CInt("0" & ad(i).Substring(k, 1))).ToString Next 'total = vb.Right(res, 1) & total total = res.Substring(res.Length - 1, 1) & total If res.Length - 1 < 1 Then resto = "0" Else resto = res.Substring(0, res.Length - 1) End If Next If resto <> "0" Then total = resto & total End If ' Return total End Function ' Private Shared Function restar2Filas() As String Dim m As Integer = 0 Dim n As Integer = ad.Length - 1 ' For k As Integer = 0 To n If ad(k).Length > m Then m = ad(k).Length Next ' ' restar las filas obtenidas Dim resto As String = "0" Dim total As String = "" Dim res As String = "" ' For k As Integer = 0 To n 'ad(k) = vb.Right(New String(" "c, m) & ad(k), m) ad(k) = (New String("0"c, m) & ad(k)).Substring(ad(k).Length, m) Next For k As Integer = m - 1 To 0 Step -1 res = (CInt("0" & ad(0).Substring(k, 1)) - (CInt("0" & ad(1).Substring(k, 1)) + CInt(resto))).ToString If CInt(res) < 0 Then res = (CInt(res) + 10).ToString res = "1" & res End If 'total = vb.Right(res, 1) & total total = res.Substring(res.Length - 1, 1) & total If res.Length - 1 < 1 Then resto = "0" Else resto = res.Substring(0, res.Length - 1) End If Next If resto <> "0" Then total = resto & total End If ' Return total End Function ' Public Shared Sub Swap(ByRef n1 As String, ByRef n2 As String) Dim t As String = n1 n1 = n2 n2 = t End Sub ' Private Shared Function quitarCeros(ByVal num As String) As String ' ' Si tiene varios ceros, dejar sólo uno While num.StartsWith("0") If num = "0" Then Exit While num = num.Substring(1) End While Return num End Function Private Shared Function quitarCerosFinales(ByVal num As String) As String ' ' Si tiene varios ceros, dejar sólo uno While num.EndsWith("0") If num = "0" Then Exit While num = num.Substring(0, num.Length - 1) End While Return num End Function End Class End Namespace
El código de prueba
using System; using elGuille.Math; class PruebaRealCS{ static void Main(string[] args) { // Real r1; Real r2; r1.Valor = "250"; r2.Valor = "2"; Console.WriteLine("{0} + {1} = {2}",r1, r2, r1 + r2); string s1 = "22"; Console.WriteLine("{0} + {1} = {2}", s1, r2, s1 + r2); // string s2 = r1; string s3 = "125"; Real r3; r3 = (Real)s3; Console.WriteLine("s2 = {0}", s2); Console.WriteLine("r3 = {0}", r3); // int i1 = 139; Real r4 = i1; Console.WriteLine("r4 = {0}", r4); Real r5 = r4 + i1; Console.WriteLine("r4 + i1 = {0}", r5); // decimal m1 = 125.50M; Real r6 = m1; Console.WriteLine("r6 = {0}", r6); // Real r7 = new Real("125.46"); Console.WriteLine("r7 = {0}", r7); // long l1 = 125987; Real r8 = l1; Console.WriteLine("r8 = {0}", r8); // float f1 = 1234.440F; Real r9 = (double)f1; Console.WriteLine("r9 = {0}", r9); // Console.Write("EsMenor(9988.5578, 1239.95) = "); Console.WriteLine(Real.EsMenor("9988.5578","1239.95")); Console.Write("EsMenor(123456, 12398745) "); Console.WriteLine(Real.EsMenor("123456","12398745")); Console.Write("EsMenor(123456789, 12398745) "); Console.WriteLine(Real.EsMenor("123456789","12398745")); // Console.WriteLine("{0} > {1} = {2}",r7, r8, r7 > r8); Console.WriteLine("{0} < {1} = {2}",r7, r8, r7 < r8); // // Console.ReadLine(); return; // } // private static void pruebaPot() { Console.WriteLine("Prueba de Potencia"); Console.WriteLine(); // string num1; string num2; Real.NumDecimales = 4; Real.MostrarResto = true; Console.WriteLine("Decimales: {0}", Real.NumDecimales); Console.WriteLine("Mostrar resto: {0}", Real.MostrarResto); Console.WriteLine(); num1 = "5"; num2 = "2"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "2"; num2 = "3"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "25"; num2 = "2"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "10"; num2 = "3"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "2"; num2 = "2.5"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "2.25"; num2 = "2"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "2"; num2 = "1"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); num1 = "2"; num2 = "0"; Console.WriteLine("{0} ^ {1} = {2}", num1, num2, Real.PotN(num1, num2)); Console.WriteLine(); // Console.ReadLine(); } // private static void pruebaResta() { Console.WriteLine("Prueba de Restar"); Console.WriteLine(); // string num1; string num2; Real.NumDecimales = 4; Real.MostrarResto = true; Console.WriteLine("Decimales: {0}", Real.NumDecimales); Console.WriteLine("Mostrar resto: {0}", Real.MostrarResto); Console.WriteLine(); Real r1 = new Real("12"); Real r2; r2.Valor = "3"; Console.WriteLine("{0} - {1} = {2}", r1, r2, r1 - r2); Console.WriteLine(); r1.Valor = "25"; r2.Valor = "4.5"; Console.WriteLine("{0} - {1} = {2}", r1, r2, r1 - r2); Console.WriteLine(); r1 = "10"; r2 = "2.25"; Console.WriteLine("{0} - {1} = {2}", r1, r2, r1 - r2); Console.WriteLine(); r1 = "2.50"; r2 = "2.25"; Console.WriteLine("{0} - {1} = {2}", r1, r2, r1 - r2); Console.WriteLine(); num1 = "22.50"; num2 = "92.25"; Console.WriteLine("{0} - {1} = {2}", num1, num2, Real.Resta2(num1, num2)); Console.WriteLine(); // Console.ReadLine(); } // private static void pruebaSuma() { Console.WriteLine("Prueba de Sumar"); Console.WriteLine(); // string num1; string num2; Real.NumDecimales = 4; Real.MostrarResto = true; Console.WriteLine("Decimales: {0}", Real.NumDecimales); Console.WriteLine("Mostrar resto: {0}", Real.MostrarResto); Console.WriteLine(); num1 = "12"; num2 = "3"; Console.WriteLine("{0} + {1} = {2}", num1, num2, Real.Suma2(num1, num2)); Console.WriteLine(); num1 = "25"; num2 = "4.5"; Console.WriteLine("{0} + {1} = {2}", num1, num2, Real.Suma2(num1, num2)); Console.WriteLine(); num1 = "10"; num2 = "2.25"; Console.WriteLine("{0} + {1} = {2}", num1, num2, Real.Suma2(num1, num2)); Console.WriteLine(); num1 = "2.50"; num2 = "2.25"; Console.WriteLine("{0} + {1} = {2}", num1, num2, Real.Suma2(num1, num2)); Console.WriteLine(); // Console.ReadLine(); } // private static void pruebaMult() { Console.WriteLine("Prueba de Multiplicar"); Console.WriteLine(); // string num1; string num2; Real.NumDecimales = 4; Real.MostrarResto = true; Console.WriteLine("Decimales: {0}", Real.NumDecimales); Console.WriteLine("Mostrar resto: {0}", Real.MostrarResto); Console.WriteLine(); num1 = "12"; num2 = "3"; Console.WriteLine("{0} * {1} = {2}", num1, num2, Real.Mult2(num1, num2)); Console.WriteLine(); num1 = "25"; num2 = "4.5"; Console.WriteLine("{0} * {1} = {2}", num1, num2, Real.Mult2(num1, num2)); Console.WriteLine(); num1 = "10"; num2 = "2.25"; Console.WriteLine("{0} * {1} = {2}", num1, num2, Real.Mult2(num1, num2)); Console.WriteLine(); num1 = "10"; num2 = "100"; Console.WriteLine("{0} * {1} = {2}", num1, num2, Real.Mult2(num1, num2)); Console.WriteLine(); num1 = "10.5"; num2 = "20.25"; Console.WriteLine("{0} * {1} = {2}", num1, num2, Real.Mult2(num1, num2)); Console.WriteLine(); // Console.ReadLine(); } // private static void pruebaDiv() { Console.WriteLine("Prueba de Dividir"); Console.WriteLine(); // string num1; string num2; Real.NumDecimales = 4; Real.MostrarResto = true; Console.WriteLine("Decimales: {0}", Real.NumDecimales); Console.WriteLine("Mostrar resto: {0}", Real.MostrarResto); Console.WriteLine(); num1 = "10"; num2 = "3"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); num1 = "9"; num2 = "4"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); num1 = "155"; num2 = "50"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); num1 = "10000"; num2 = "225"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); num1 = "100"; num2 = "2.25"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); num1 = "10"; num2 = "2.5"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); num1 = "100"; num2 = "2.5"; Console.WriteLine("{0} / {1} = {2}", num1, num2, Real.Div2(num1, num2)); Console.WriteLine(); // Console.ReadLine(); } private static void pruebaTodos() { pruebaDiv(); pruebaMult(); pruebaSuma(); pruebaResta(); pruebaPot(); } }
El código de la estructura
//----------------------------------------------------------------------------- // Multiplicar números usando cadenas de caracteres (10/Ago/04) // // Realizar operaciones con números de cualquier longitud // Admite decimales (11/Ago/04) // // Operaciones soportadas: // Multiplicación, División, Potencia, Suma y Resta // // ©Guillermo 'guille' Som, 2004 //----------------------------------------------------------------------------- using System; namespace elGuille.Math{ public struct Real{ internal static string[] ad; public static int NumDecimales = 4; public static bool MostrarResto = false; public string Valor; // = "0"; // public Real(string num) { int i = num.IndexOf("."); if(i > -1) if(num.Substring(i).Length > NumDecimales) num = num.Substring(0, i) + "." + num.Substring(i+1, NumDecimales); else num = num.Substring(0, i) + "." + num.Substring(i+1); Valor = num; ad = new string[1]; ad[0] = num; } // sobrecarga de operadores public static Real operator +(Real r1, Real r2) { return new Real(Suma2(r1.Valor, r2.Valor)); } public static Real operator +(Real r1, string r2) { return new Real(Suma2(r1.Valor, r2)); } public static Real operator +(string r1, Real r2) { return new Real(Suma2(r1, r2.Valor)); } // public static Real operator -(Real r1, Real r2) { return new Real(Resta2(r1.Valor, r2.Valor)); } public static Real operator -(Real r1, string r2) { return new Real(Resta2(r1.Valor, r2)); } public static Real operator -(string r1, Real r2) { return new Real(Resta2(r1, r2.Valor)); } // public static Real operator *(Real r1, Real r2) { return new Real(Mult2(r1.Valor, r2.Valor)); } public static Real operator *(Real r1, string r2) { return new Real(Mult2(r1.Valor, r2)); } public static Real operator *(string r1, Real r2) { return new Real(Mult2(r1, r2.Valor)); } // public static Real operator /(Real r1, Real r2) { return new Real(Div2(r1.Valor, r2.Valor)); } public static Real operator /(Real r1, string r2) { return new Real(Div2(r1.Valor, r2)); } public static Real operator /(string r1, Real r2) { return new Real(Div2(r1, r2.Valor)); } // // convertir de Real a string public static implicit operator string(Real r1) { return r1.Valor; } // convertir de string a Real public static implicit operator Real(string r1) { return new Real(r1); } // convertir de Real a int public static explicit operator int(Real r1) { try{ return int.Parse(r1.Valor); }catch{ return 0; } } // Esta conversión no es necesaria si está la de long // // convertir de int a Real // public static implicit operator Real(int r1) // { // return new Real(Convert.ToString(r1)); // } // convertir de long a Real public static implicit operator Real(long r1) { return new Real(Convert.ToString(r1)); } // convertir de decimal a Real public static implicit operator Real(decimal r1) { string s = Convert.ToString(r1).Replace(",",".") ; return new Real(s); } // convertir de double a Real public static implicit operator Real(double r1) { string s = Convert.ToString(r1).Replace(",",".") ; return new Real(s); } // // public static bool operator <(Real r1, Real r2) { return Real.EsMenor(r1.Valor, r2.Valor); } public static bool operator >(Real r1, Real r2) { return !Real.EsMenor(r1.Valor, r2.Valor); } // public static bool operator ==(Real r1, Real r2) { return r1.Valor == r2.Valor; } public static bool operator !=(Real r1, Real r2) { return r1.Valor != r2.Valor; } // // public override string ToString() { return Valor; } // // public static bool EsMenor(string num1, string num2) { // comparar dos cadenas para ver cual es menor // deben tener el mismo número de digitos // antes y después del decimal int nDec1 = num1.IndexOf("."); int nDec2 = num2.IndexOf("."); int i = nDec1; if(i > -1){ num1 = num1 + new string('0', NumDecimales); num1 = num1.Substring(0, i) + "." + num1.Substring(i+1, NumDecimales); } i = nDec2; if(i > -1){ num2 = num2 + new string('0', NumDecimales); num2 = num2.Substring(0, i) + "." + num2.Substring(i+1, NumDecimales); } // ajustar los dos tamaños al mayor if(nDec1 == -1 && nDec2 == -1){ nDec1 = num1.Length; nDec2 = num2.Length; } if(nDec1 == -1) nDec1 = num1.Length; if(nDec2 == -1) nDec2 = num2.Length; if(nDec1 > nDec2) num2 = (new string('0', nDec1) + num2); if(nDec2 > nDec1) num1 = (new string('0', nDec2) + num1); // if(string.Compare(num1, num2) < 0) return true; else return false; } // private static string miDiv2(string num1, string num2, int decAct) { string res = num1; int n = 0; if( num2.Length < num1.Length ){ num2 = (new string('0', num1.Length) + num2).Substring(num2.Length, num1.Length); } while(true){ res = miResta2(res, num2); n += 1; if( res == "0" || string.Compare(res, num2)< 0 ) break; } res = quitarCeros(res); if( res != "0" ){ if( decAct < NumDecimales ){ decAct += 1; res = miDiv2(res + "0", num2, decAct); // quitar los puntos que haya res = res.Replace(".", ""); return n.ToString() + "." + res; }else{ // si queda un resto mostrarlo con : // (o bien no mostrarlo) if( MostrarResto ){ return n.ToString() + ":" + res; }else{ return n.ToString(); } } }else{ return n.ToString(); } } public static string Div2(string num1, string num2) { // Para dividir dos números: // Se leva restando al dividendo el divisor hasta que // el resto sea cero o menor que el divisor int decAct = 0; // int nDec1 = 0; int nDec2 = 0; int dec1 = num1.IndexOf("."); int dec2 = num2.IndexOf("."); if( dec1 > -1 ){ num1 = quitarCerosFinales(num1); nDec1 = num1.Substring(dec1 + 1).Length; num1 = num1.Replace(".", ""); } if( dec2 > -1 ){ num2 = quitarCerosFinales(num2); nDec2 = num2.Substring(dec2 + 1).Length; num2 = num2.Replace(".", ""); } if( nDec1 > 0 ){ num2 = num2 + new string('0', nDec1); } if( nDec2 > 0 ){ num1 = num1 + new string('0', nDec2); } // return miDiv2(num1, num2, decAct); } // public static string PotN(string num1, string elevado) { int i; // // si el exponente tiene decimales, quitárselo i = elevado.IndexOf("."); if( i > -1 ){ elevado = elevado.Substring(0, i); } // if( elevado == "0" ){ return "1"; }else if( elevado == "1" ){ return num1; } if( num1 == "1" ){ return "1"; }else if( num1 == "0" ){ return "0"; } // i = Convert.ToInt32(elevado); string[] p = new string[i]; for(int k = 0; k < i; k++){ p[k] = num1; } return Mult2(p); } // public static string Mult2( params string[] nums) { string total = nums[0]; for(int i= 1; i< nums.Length; i++){ string n1 = nums[i]; total = Mult2(total, n1); } // return total; } // public static string Mult2(string num1, string num2) { // // Comprobar si alguno de los números tiene decimales (11/Ago/04) int nDec = 0; // int dec1 = num1.IndexOf("."); int dec2 = num2.IndexOf("."); if( dec1 > -1 ){ nDec = num1.Substring(dec1 + 1).Length; num1 = num1.Replace(".", ""); } if( dec2 > -1 ){ nDec += num2.Substring(dec2 + 1).Length; num2 = num2.Replace(".", ""); } // // Poner el más largo como primer número if( num2.Length > num1.Length ){ Swap(ref num1, ref num2); } // // El número de operaciones necesarias // será la cantidad de cifras del más pequeño ad = new string[num2.Length]; int n = -1; string resto = "0"; string res = ""; // // Multiplicar formando filas con los resultados (al estilo manual) for(int i= num2.Length - 1; i>= 0; i--){ n += 1; ad[n] = ""; // Añadir espacios a la derecha según la cifra (fila) que se procese for(int k= 1; k<= n; k++){ ad[n] += " "; } string c1 = num2.Substring(i, 1); // Para simplificar las cosas // se comprueba si se multiplicará por ceo o por uno // de forma que no sea necesario hacer estas operaciones if( c1 == "0" ){ ad[n] = new string('0', num1.Length) + ad[n]; }else if( c1 == "1" ){ ad[n] = num1 + ad[n]; }else{ for(int j= num1.Length - 1; j>= 0; j--){ string c2 = num1.Substring(j, 1); res = (Convert.ToInt32("0" + c1) * Convert.ToInt32("0" + c2) + Convert.ToInt32(resto)).ToString(); ad[n] = res.Substring(res.Length - 1, 1) + ad[n]; if( res.Length - 1 < 1 ){ resto = "0"; }else{ resto = res.Substring(0, res.Length - 1); } } if( resto != "0" ){ ad[n] = resto + ad[n]; resto = "0"; } } } // res = sumarFilas(); if( nDec > 0 ){ if( NumDecimales == 0 ){ res = res.Substring(0, res.Length - nDec); }else{ resto = res.Substring(res.Length - nDec); if( resto.Length > NumDecimales ){ resto = resto.Substring(0, NumDecimales); } res = res.Substring(0, res.Length - nDec) + "." + quitarCerosFinales(resto); } } return res; } // public static string Suma2( params string[] nums) { // ad = new string[nums.Length]; for(int i= 0; i< nums.Length; i++){ ad[i] = nums[i]; } // return sumarFilas(); } // public static string Suma2(string num1, string num2) { ad = new string[2]; // int nDec = 0; int nDec1 = 0; int nDec2 = 0; int dec1 = num1.IndexOf("."); int dec2 = num2.IndexOf("."); if( dec1 > -1 ){ num1 = quitarCerosFinales(num1); nDec1 = num1.Substring(dec1 + 1).Length; num1 = num1.Replace(".", ""); } if( dec2 > -1 ){ num2 = quitarCerosFinales(num2); nDec2 = num2.Substring(dec2 + 1).Length; num2 = num2.Replace(".", ""); } if( nDec1 > 0 ){ num2 = num2 + new string('0', nDec1); } if( nDec2 > 0 ){ num1 = num1 + new string('0', nDec2); } nDec = nDec1 + nDec2; // ad[0] = num1; ad[1] = num2; // //Return sumarFilas() // string res = sumarFilas(); string resto = ""; if( nDec > 0 ){ if( NumDecimales == 0 ){ res = res.Substring(0, res.Length - nDec); }else{ resto = res.Substring(res.Length - nDec); if( resto.Length > NumDecimales ){ resto = resto.Substring(0, NumDecimales); } res = res.Substring(0, res.Length - nDec) + "." + quitarCerosFinales(resto); } } return res; } // public static string Resta2( params string[] nums) { string total = nums[0]; for(int i= 1; i<= nums.Length - 1; i++){ string n1 = nums[i]; //total = Resta2(total, n1) total = miResta2(total, n1); } // return total; } // private static string miResta2(string num1, string num2) { // usar esta función para cálculos internos en los que no se deben quitar // los ceros del principio del número ad = new string[2]; // int nDec = 0; int nDec1 = 0; int nDec2 = 0; int dec1 = num1.IndexOf("."); int dec2 = num2.IndexOf("."); if( dec1 > -1 ){ num1 = quitarCerosFinales(num1); nDec1 = num1.Substring(dec1 + 1).Length; num1 = num1.Replace(".", ""); } if( dec2 > -1 ){ num2 = quitarCerosFinales(num2); nDec2 = num2.Substring(dec2 + 1).Length; num2 = num2.Replace(".", ""); } if( nDec1 > 0 ){ num2 = num2 + new string('0', nDec1); } if( nDec2 > 0 ){ num1 = num1 + new string('0', nDec2); } nDec = nDec1 + nDec2; // ad[0] = num1; ad[1] = num2; // //Return restar2Filas() // string res = restar2Filas(); string resto = ""; if( nDec > 0 ){ if( NumDecimales == 0 ){ res = res.Substring(0, res.Length - nDec); }else{ resto = res.Substring(res.Length - nDec); if( resto.Length > NumDecimales ){ resto = resto.Substring(0, NumDecimales); } res = res.Substring(0, res.Length - nDec) + "." + quitarCerosFinales(resto); } } return res; } // public static string Resta2(string num1, string num2) { return quitarCeros(miResta2(num1, num2)); // } // private static string sumarFilas() { int m = 0; int n = ad.Length - 1; // // m será el número de mayor longitud for(int k= 0; k<= n; k++){ if( ad[k].Length > m ) m = ad[k].Length; } // // sumar las filas obtenidas string resto = "0"; string total = ""; string res = ""; // for(int k= 0; k<= n; k++){ ad[k] = (new string(' ', m) + ad[k]).Substring(ad[k].Length, m); } for(int k= m - 1; k>= 0; k--){ res = resto; for(int i= 0; i<= n; i++){ res = (Convert.ToInt32(res) + Convert.ToInt32("0" + ad[i].Substring(k, 1))).ToString(); } total = res.Substring(res.Length - 1, 1) + total; if( res.Length - 1 < 1 ){ resto = "0"; }else{ resto = res.Substring(0, res.Length - 1); } } if( resto != "0" ){ total = resto + total; } // return total; } // private static string restar2Filas() { int m = 0; int n = ad.Length - 1; // for(int k= 0; k<= n; k++){ if( ad[k].Length > m ) m = ad[k].Length; } // // restar las filas obtenidas string resto = "0"; string total = ""; string res = ""; // for(int k= 0; k<= n; k++){ ad[k] = (new string('0', m) + ad[k]).Substring(ad[k].Length, m); } for(int k= m - 1; k>= 0; k--){ res = (Convert.ToInt32("0" + ad[0].Substring(k, 1)) - (Convert.ToInt32("0" + ad[1].Substring(k, 1)) + Convert.ToInt32(resto))).ToString(); if( Convert.ToInt32(res) < 0 ){ res = (Convert.ToInt32(res) + 10).ToString(); res = "1" + res; } total = res.Substring(res.Length - 1, 1) + total; if( res.Length - 1 < 1 ){ resto = "0"; }else{ resto = res.Substring(0, res.Length - 1); } } if( resto != "0" ){ total = resto + total; } // return total; } // public static void Swap(ref string n1, ref string n2) { string t = n1; n1 = n2; n2 = t; } // private static string quitarCeros(string num) { // // Si tiene varios ceros, dejar sólo uno while( num.StartsWith("0")){ if( num == "0" ) break; num = num.Substring(1); } return num; } private static string quitarCerosFinales(string num) { // // Si tiene varios ceros, dejar sólo uno while( num.EndsWith("0")){ if( num == "0" ) break; num = num.Substring(0, num.Length - 1); } return num; } } }
El código para Visual Basic 6.0 (o anteriores a VB .NET)
El código de VB6 es el de la versión anterior.