Introducción
El otro día estaba intentando hacer operaciones
con números demasiado grandes (de por ejemplo 97 cifras cada uno) pero resulta
que si bien el .NET puede realizarlas, al final acaba haciéndolo con valores
de tipo Double y usando notación científica, con lo que no me servía ya que
necesitaba que todos los dígitos fuesen válidos y estuviesen a la vista... al
final, acabé maldiciendo al .NET y la falta de previsión de ese tipo de
operaciones.
Buscando por la Web me
encontré con programas especializados (y en la mayoría de los casos, con unos
precios descomunales), lo único válido que encontré, además del amzi!
Prolog, fue la aplicación "bc GNU" (bc - An arbitrary precision
calculator language) una aplicación que permite realizar ciertas operaciones
que no nos limitan el número de dígitos, además de que también podemos indicar
si queremos o no usar decimales, este lenguaje "calculador" tiene ciertas
instrucciones como la de realizar bucles for o bucles while de forma más o
menos fácil, al menos para mi, que eso de Prolog me resultaba algo
"enrevesado" para hacer ciertas cosas "simples".
La cuestión es que para los cálculos estoy
usando bc, pero me dije que sería interesante poder realizar ese tipo de
cálculos en .NET (e incluso en VB6).
Y aquí está lo que por ahora he hecho con esto
de los números enteros de cualquier cantidad de dígitos:
-Sumar dos números (o varios) enteros de cualquier cantidad de dígitos,
-Multiplicar dos (o varios) números
-Realizar exponenciaciones (elevar un número a cualquier otro)
-Restar dos números (o varios)
Por
ahora no me he puesto a usar números con fracciones decimales ni a realizar la
división, para eso necesitaré la ayuda de algún "matemático" que me explique
cómo hacer ese tipo de operaciones trabajando individualmente con los dígitos
que componen el número... ya que de eso se trata: de ir operando con cada uno
de los dígitos de forma individual... tal y como lo hacemos manualmente.
En fin... si alguien se anima... pues
podríamos hacer algo que realmente sea útil...
Mi idea será, en principio, crear un tipo de
datos (una estructura) en C# en la que poder crear sobrecargas de operadores y
conversiones a otros tipos de datos, cuando la versión 2005 de VB esté más
avanzada, convertiré ese código a VB ya que en la versión 2005 se podrán crear
sobrecargas de operadores y demás cosillas que actualmente sólo se pueden
hacer con C#.
Aquí te pongo
el código para VB .NET 2003 (será fácil convertirlo a la
versión 2002, ya que realmente sólo hago uso de la declaración de variables en
los bucles).
También pondré el código de C# y
el código para VB6, así
que... sigue comprobando esta página ya que seguramente habrá novedades
pronto... al menos eso espero.
Para probar el código
(y los resultados)
Para que
puedas probar desde la línea de comandos, el proyecto (de consola) recibe
argumentos de la línea de comandos, esos argumentos serán los dos números con
los que operar y la operación a realizar.
Es decir, se indicarán los números con los que se deben operar y después la
operación a realizar (a esto se le llama notación Polaca, por si te interesa
saberlo).
Las operaciones podrán ser: * multiplicar, + sumar, - restar y ** elevar a una
potencia, por ejemplo:
multStr 1234567890123456789012345 123456789 *
multStr 125 500 **
Por supuesto,
para comprobar que todas estas operaciones devuelven un resultado correcto
tendrás que usar algún programa que sea capaz de realizarlas!!!
En el caso de 125 elevado a 500... ¡¡¡el número tendrá 1049 dígitos!!!
Para comprobar los resultados, también puedes
usar GNU bc, (desde la lista de referencias puedes
bajar el ejecutable, la documentación y el código), aunque para usarla debes
crear un fichero que realice las operaciones que quieres realizar y después
llamar a bc.exe, por ejemplo, puedes crear un fichero llamado "pruebas.bc" con
el siguiente contenido:
res = 1234567890123456789012345 *
123456789
print res, "\n\n"
res = 125 ^ 500
print "125 ^ 500 = \n", res, "\n"
quit
Y después usarla de esta forma:
bc pruebas.bc
Las funciones incluidas (los tipos de
operaciones soportadas)
Aunque
en este primer intento, (que hice anoche), todo el código está en el mismo
módulo, al menos te indicaré las funciones que tiene y para que sirven, así,
si quieres modificarlo, sepas de forma más fácil cómo funciona.
En algunas funciones se permiten dos parámetros
o un array de varios parámetros, por ejemplo, si quieres multiplicar dos
números puedes llamar a la función Mult2(n1, n2) indicando los dos números a
multiplicar, pero si quieres realizar varias operaciones de multiplicación,
puedes llamar a Mult2(n1, n2, n3, ... nN).
cada función se indicará seguida de /2 si recibe 2 parámetros y/o de
/N si recibe N parámetros. Esta es una notación que usa en Prolog para
indicar el número de parámetros que recibe cada función, y como me gusta...
Todas las funciones devuelven una cadena con el resultado.
- Mult2 (Mult2/2 y Mult2/N)
Multiplica dos (o N números).
- PotN (PotN/2)
Eleva el primer número a la potencia indicada (realmente multiplica N
veces el primer número indicado)
- Resta2 (Resta2/2 y Resta2/N)
Resta 2 números o N números
- Suma2 (suma2/2 y Suma2/N)
Suma 2 o más números
- Div2 (Div2/2) (rev
0.1)
Divide dos números
- Sobrecargado los operadores *, /, +,
-, >, <, ==, != (rev 0.2)
Esto sólo para la versión de C#
- Sobrecargado los operadores ++, --
(rev 0.3, por publicar)
Esto sólo para la versión de C#
Internamente se usan las siguientes funciones
y variables:
- ad() un array con cada uno de los
números con los que hay que operar
Mult2 calcula cada una de las líneas y las guarda en el array ad() que
posteriormente se sumará para conseguir el resultado.
- swap cambia el contenido de los
dos parámetros indicados, los parámetros se pasarán por referencia. Este
método lo uso para poner primero el número más largo y después el más
corto.
- sumarFilas, suma el contenido del
array ad() (cada uno de los elementos) y devuelve el resultado.
- restar2Filas, resta los dos
primeros elementos del array ad() y devuelve el resultado.
Nos
vemos.
Guillermo
Referencias
Colaborar en este proyecto
Si quieres, puedes participar en este
proyecto, creo que puede ser interesante.
La idea es conseguir hacer cálculos con números bastantes grandes (de muchos
dígitos) y por supuesto hacerlo lo más rápido posible, ya que, por ejemplo, el
código de elevar a potencias, es relativamente lento...
Las cosas que tengo anotadas por hacer:
(revisa siempre la última actualización
para saber que es lo que hay pendiente de hacer)
- Trabajar con decimales (hecho rev 0.1)
- Dividir números (hecho rev 0.1)
- Calcular la raíz cuadrada
- Trabajar con números negativos
- ...lo que se me ocurra o lo que
propongas...
Así que si te animas... me mandas un mensaje
a: mensaje @ elguille.info con el asunto "Participar en numeros
grandes" y ya hablamos.
Gracias.
Nota del 17/Ene/2019:
Esto es de hace 15 años, así que... si después de verlo nuevamente quieres colaborar...
pues... no sé si lo volveré a retomar, de todas formas ya hice en su día cosas nuevas
(usando DLL de F#) y... bueno, lo publiqué en ProgramarPorProgramar.org y... actualmente
ese sitio ya no va... (pero lo quiero reactivar ya que el dominio lo tengo pagado ;-) )
Pero ya te digo... si me escribes y no te respondo, pues... que no te lo tomes a mal.
Gracias.
El código para VB .NET
'------------------------------------------------------------------------------
' Multiplicar números usando cadenas de caracteres (10/Ago/04)
' Realizar operaciones con números enteros de cualquier longitud
' Operaciones soportadas:
' Multiplicación, Potencias, Suma y Resta
'
' ©Guillermo 'guille' Som, 2004
'------------------------------------------------------------------------------
Option Explicit On
Option Strict On
Imports vb = Microsoft.VisualBasic
Imports System
Module MultStr
Dim ad() As String
'
Sub Main(ByVal args() As String)
'
'Console.WriteLine("125 ^ 9 = {0}", 125 ^ 9)
'Console.WriteLine()
'
Dim num1 As String = "123"
Dim num2 As String = "123"
Dim op As String = "*"
If args.Length > 1 Then
num1 = args(0)
num2 = args(1)
End If
If num2.Length > num1.Length Then
swap(num1, num2)
End If
'
If args.Length = 3 Then
op = args(2)
End If
'
Select Case op
Case "+"
Console.WriteLine(Suma2(num1, num2))
Case "-"
Console.WriteLine(Resta2(num1, num2))
Case "**"
Console.WriteLine(PotN(num1, num2))
Case "*", "x"
Console.WriteLine(Mult2(num1, num2))
'
' Para mostrar todas las cifras que intervienen
' en las operaciones, comenta esto si sólo quieres el resultado
Dim res As String = Mult2(num1, num2)
Dim k As Integer = res.Length
Console.WriteLine(" {0," & k.ToString & "}", num1)
Console.WriteLine("x {0," & k.ToString & "}", num2)
Console.WriteLine(New String("-"c, k + 2))
For i As Integer = 0 To ad.Length - 1
Console.WriteLine(" {0," & k.ToString & "}", ad(i))
Next
Console.WriteLine(New String("-"c, k + 2))
Console.WriteLine(" {0," & k.ToString & "}", res)
End Select
End Sub
'
'
Public Function PotN(ByVal num1 As String, ByVal elevado As String) As String
Dim i As Integer = 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 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 Function Mult2(ByVal num1 As String, ByVal num2 As String) As String
'
' 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)
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
'
Return sumarFilas()
End Function
'
Public 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 Function Suma2(ByVal num1 As String, ByVal num2 As String) As String
ReDim ad(1)
ad(0) = num1
ad(1) = num2
'
Return sumarFilas()
End Function
'
Public 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 = Resta2(total, n1)
Next
'
Return total
End Function
'
Public Function Resta2(ByVal num1 As String, ByVal num2 As String) As String
ReDim ad(1)
ad(0) = num1
ad(1) = num2
'
Return restar2Filas()
End Function
'
Private 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)
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
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 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)
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
End If
total = vb.Right(res, 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 Sub swap(ByRef n1 As String, ByRef n2 As String)
Dim t As String = n1
n1 = n2
n2 = t
End Sub
End Module
El código para C#
//-----------------------------------------------------------------------------
// Multiplicar números usando cadenas de caracteres (10/Ago/04)
// Realizar operaciones con números enteros de cualquier longitud
//
// Operaciones soportadas:
// Multiplicación, Potencias, Suma y Resta
//
// ©Guillermo 'guille' Som, 2004
//-----------------------------------------------------------------------------
using System;
class MultStr{
private static string[] ad;
//
[STAThread]
static void Main(string[] args) {
//
string num1 = "123";
string num2 = "123";
string op = "*";
if( args.Length > 1 ){
num1 = args[0];
num2 = args[1];
}
if( num2.Length > num1.Length ){
swap(ref num1, ref num2);
}
//
if( args.Length == 3 ){
op = args[2];
}
//
switch(op){
case "+":
Console.WriteLine(Suma2(num1, num2));
break;
case "-":
Console.WriteLine(Resta2(num1, num2));
break;
case "**":
Console.WriteLine(PotN(num1, num2));
break;
case "*":
case "x":
Console.WriteLine(Mult2(num1, num2));
//
// Para mostrar todas las cifras que intervienen
string res = Mult2(num1, num2);
int k = res.Length;
Console.WriteLine(" {0," + k.ToString() + "}", num1);
Console.WriteLine("x {0," + k.ToString() + "}", num2);
Console.WriteLine(new string('-', k + 2));
for(int i= 0; i<= ad.Length - 1; i++){
Console.WriteLine(" {0," + k.ToString() + "}", ad[i]);
}
Console.WriteLine(new string('-', k + 2));
Console.WriteLine(" {0," + k.ToString() + "}", res);
break;
}
//
Console.ReadLine();
}
//
//
public static string PotN(string num1, string elevado) {
int i = Convert.ToInt32(elevado) - 1;
string[] p = new string[(i + 1)];
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 - 1; i++){
string n1 = nums[i];
total = Mult2(total, n1);
}
//
return total;
}
//
public static string Mult2(string num1, string num2) {
//
// 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";
}
}
}
//
return sumarFilas();
}
//
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];
ad[0] = num1;
ad[1] = num2;
//
return sumarFilas();
}
//
public static string Resta2( params string[] nums) {
string total = nums[0];
for(int i= 1; i< nums.Length; i++){
string n1 = nums[i];
total = Resta2(total, n1);
}
//
return total;
}
//
public static string Resta2(string num1, string num2) {
ad = new string[2];
ad[0] = num1;
ad[1] = num2;
//
return restar2Filas();
}
//
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(' ', 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();
}
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 void swap(ref string n1, ref string n2) {
string t = n1;
n1 = n2;
n2 = t;
}
}
El código para Visual Basic 6.0
(o anteriores a VB .NET)
El formulario de
prueba (y una captura en tiempo de ejecución)
El formulario en tiempo de ejecución.
'------------------------------------------------------------------------------
' Realizar operaciones con números grandes usando cadenas (10/Ago/04)
' Formulario de prueba para Visual Basic 6.0
'
' Realizar operaciones con números enteros de cualquier longitud
' Operaciones soportadas:
' Multiplicación, Potencia, Suma y Resta
'
' ©Guillermo 'guille' Som, 2004
'------------------------------------------------------------------------------
Option Explicit
Private Sub cmdCalcular_Click()
Select Case Left$(cboOp.Text, 1)
Case "+"
txtRes.Text = Suma2(txtNum1.Text, txtNum2.Text)
Case "-"
txtRes.Text = Resta2(txtNum1.Text, txtNum2.Text)
Case "*"
txtRes.Text = Mult2(txtNum1.Text, txtNum2.Text)
Case "^"
txtRes.Text = PotN(txtNum1.Text, txtNum2.Text)
End Select
End Sub
Private Sub Form_Load()
With cboOp
.Clear
.AddItem ("+ - Sumar")
.AddItem ("- - Restar")
.AddItem ("* - Multiplicar")
.AddItem ("^ - Elevar a potencia")
.ListIndex = 2
End With
txtNum1.Text = "1234567890123456789012345"
txtNum2.Text = "12345678901234567890"
txtRes.Text = ""
End Sub
Private Sub Form_Resize()
If WindowState <> vbMinimized Then
txtNum1.Width = ScaleWidth - txtNum1.Left - 240
txtNum2.Width = txtNum1.Width
cmdCalcular.Left = ScaleWidth - cmdCalcular.Width - 240
txtRes.Width = txtNum1.Width
txtRes.Height = ScaleHeight - txtRes.Top - 240
End If
End Sub
El código del módulo con las funciones
'------------------------------------------------------------------------------
' Módulo con las funciones para realizar los cálculos (10/Ago/04)
' Versión para Visual Basic 6.0
'
' Realizar operaciones con números enteros de cualquier longitud
' Operaciones soportadas:
' Multiplicación, Potencia, Suma y Resta
'
' ©Guillermo 'guille' Som, 2004
'------------------------------------------------------------------------------
Option Explicit
Private ad() As String
Public Function PotN(ByVal num1 As String, ByVal elevado As String) As String
Dim i As Long
Dim p() As String
Dim k As Long
'
i = CLng(elevado) - 1
ReDim p(i)
For k = 0 To i
p(k) = num1
Next
PotN = Mult2N(p)
End Function
'
Public Function Mult2N(ParamArray nums() As Variant) As String
Dim total As String
Dim n1 As String
Dim i As Long
'
If IsArray(nums(0)) Then
total = nums(0)(0)
For i = 1 To UBound(nums(0))
n1 = nums(0)(i)
total = Mult2(total, n1)
Next
Else
total = nums(0)
For i = 1 To UBound(nums)
n1 = nums(i)
total = Mult2(total, n1)
Next
End If
'
Mult2N = total
End Function
'
Public Function Mult2(ByVal num1 As String, ByVal num2 As String) As String
'
' Poner el más largo como primer número
If Len(num2) > Len(num1) Then
Call swap(num1, num2)
End If
'
' El número de operaciones necesarias
' será la cantidad de cifras del más pequeño
ReDim ad(Len(num2) - 1)
Dim n As Long
n = -1
Dim resto As String
resto = "0"
Dim res As String
'
' Multiplicar formando filas con los resultados (al estilo manual)
Dim i As Long
For i = Len(num2) To 1 Step -1
n = n + 1
ad(n) = ""
' Añadir espacios a la derecha según la cifra (fila) que se procese
Dim k As Long
For k = 1 To n
ad(n) = ad(n) & " "
Next
Dim c1 As String
c1 = Mid$(num2, 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) = String$(Len(num1), "0") & ad(n)
ElseIf c1 = "1" Then
ad(n) = num1 & ad(n)
Else
Dim j As Long
For j = Len(num1) To 1 Step -1
Dim c2 As String
c2 = Mid$(num1, j, 1)
res = CStr(CLng("0" & c1) * CLng("0" & c2) + CLng(resto))
ad(n) = Right$(res, 1) & ad(n)
If Len(res) - 1 < 1 Then
resto = "0"
Else
resto = Left$(res, Len(res) - 1)
End If
Next
If resto <> "0" Then
ad(n) = resto & ad(n)
resto = "0"
End If
End If
Next
'
Mult2 = sumarFilas()
End Function
'
Public Function Suma2N(ParamArray nums() As Variant) As String
Dim i As Long
'
If IsArray(nums(0)) Then
ReDim ad(UBound(nums(0)))
For i = 0 To UBound(nums(0))
ad(i) = nums(0)(i)
Next
Else
ReDim ad(UBound(nums))
For i = 0 To UBound(nums)
ad(i) = nums(i)
Next
End If
'
Suma2N = sumarFilas()
End Function
'
Public Function Suma2(ByVal num1 As String, ByVal num2 As String) As String
ReDim ad(1)
ad(0) = num1
ad(1) = num2
'
Suma2 = sumarFilas()
End Function
'
Public Function Resta2N(ParamArray nums() As Variant) As String
Dim total As String
Dim i As Long
Dim n1 As String
'
If IsArray(nums(0)) Then
total = nums(0)(0)
For i = 1 To UBound(nums(0))
n1 = nums(0)(i)
total = Resta2(total, n1)
Next
Else
total = nums(0)
For i = 1 To UBound(nums)
n1 = nums(i)
total = Resta2(total, n1)
Next
End If
'
Resta2N = total
End Function
'
Public Function Resta2(ByVal num1 As String, ByVal num2 As String) As String
ReDim ad(1)
ad(0) = num1
ad(1) = num2
'
Resta2 = restar2Filas()
End Function
'
Private Function sumarFilas() As String
Dim i As Long
Dim k As Long
Dim m As Long
Dim n As Long
n = UBound(ad)
'
' m será el número de mayor longitud
For k = 0 To n
If Len(ad(k)) > m Then m = Len(ad(k))
Next
'
' sumar las filas obtenidas
Dim resto As String
resto = "0"
Dim total As String
Dim res As String
'
For k = 0 To n
ad(k) = Right$(String$(m, " ") & ad(k), m)
Next
For k = m To 1 Step -1
res = resto
For i = 0 To n
res = CStr(CLng(res) + CLng("0" & Mid$(ad(i), k, 1)))
Next
total = Right$(res, 1) & total
If Len(res) - 1 < 1 Then
resto = "0"
Else
resto = Left$(res, Len(res) - 1)
End If
Next
If resto <> "0" Then
total = resto & total
End If
'
sumarFilas = total
End Function
'
Private Function restar2Filas() As String
Dim k As Long
Dim m As Long
Dim n As Long
n = UBound(ad)
'
For k = 0 To n
If Len(ad(k)) > m Then m = Len(ad(k))
Next
'
' restar las filas obtenidas
Dim resto As String
resto = "0"
Dim total As String
Dim res As String
'
For k = 0 To n
ad(k) = Right$(String$(m, " ") & ad(k), m)
Next
For k = m To 1 Step -1
res = CStr(CLng("0" & Mid$(ad(0), k, 1)) - (CLng("0" & Mid$(ad(1), k, 1)) + CLng(resto)))
If CLng(res) < 0 Then
res = CStr(CLng(res) + 10)
End If
total = Right$(res, 1) & total
If Len(res) - 1 < 1 Then
resto = "0"
Else
resto = Left$(res, Len(res) - 1)
End If
Next
If resto <> "0" Then
total = resto & total
End If
'
restar2Filas = total
End Function
'
Private Sub swap(ByRef n1 As String, ByRef n2 As String)
Dim t As String
t = n1
n1 = n2
n2 = t
End Sub