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_GreaterThan
Ademá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.
El código para VB .NET
'------------------------------------------------------------------------------
' 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 para C#
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.