- Introducción
En aplicaciones donde se manejan números extremadamente grandes, los tipos nativos como int o long long no son suficientes. Esta guía explica cómo implementar operaciones aritméticas básicas (suma, resta, multiplicación y división por un entero pequeño) sobre números de gran tamaño usando arrays y manipulación manual de dígitos.
- Representación de Números Grandes
Los números con más de 20 cifras no pueden almacenarse directamente en tipos estándar. Por ello, se representa cada número como una cadena de caracteres, que luego se convierte a un array de enteros digitales. El orden inverso facilita el cálculo desde el dígito menos significativo hacia el más significativo.
2.1 Suma de Grandes Números
El proceso sigue las reglas tradicionales de suma: alineación de dígitos, suma desde la derecha, y propagación de acarreo cuando el resultado excede 9.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
string num1, num2;
cin >> num1 >> num2;
// Invertir cadenas para procesar desde el dígito menos significativo
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
int len = max(num1.length(), num2.length());
int a[len] = {}, b[len] = {}, result[len + 1] = {};
// Convertir caracteres a dígitos
for (int i = 0; i < num1.length(); ++i)
a[i] = num1[i] - '0';
for (int i = 0; i < num2.length(); ++i)
b[i] = num2[i] - '0';
// Realizar suma con acarreo
for (int i = 0; i < len; ++i) {
result[i] += a[i] + b[i];
result[i + 1] += result[i] / 10;
result[i] %= 10;
}
// Invertir resultado final y eliminar ceros iniciales
reverse(result, result + len + 1);
string output = "";
bool leading_zero = true;
for (int i = 0; i <= len; ++i) {
if (!(result[i] == 0 && leading_zero)) {
leading_zero = false;
output += result[i] + '0';
}
}
if (output.empty()) output = "0";
cout << output;
return 0;
}
2.2 Resta de Grandes Números
La resta requiere comparar magnitudes antes de proceder. Si el segundo número es mayor, el resultado será negativo. Se invierten los operandos y se añade un signo negativo si corresponde.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
string a, b;
cin >> a >> b;
string sign = "";
if (a.length() < b.length() ||
(a.length() == b.length() && a < b)) {
sign = "-";
swap(a, b);
}
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int len = max(a.length(), b.length());
int x[len] = {}, y[len] = {}, diff[len + 1] = {};
for (int i = 0; i < a.length(); ++i)
x[i] = a[i] - '0';
for (int i = 0; i < b.length(); ++i)
y[i] = b[i] - '0';
for (int i = 0; i < len; ++i) {
diff[i] += x[i] - y[i];
if (diff[i] < 0) {
diff[i] += 10;
diff[i + 1] -= 1;
}
}
reverse(diff, diff + len + 1);
string result = "";
bool leading = true;
for (int i = 0; i <= len; ++i) {
if (!(diff[i] == 0 && leading)) {
leading = false;
result += diff[i] + '0';
}
}
if (result.empty()) result = "0";
cout << sign << result;
return 0;
}
2.3 Multiplicación de Grandes Números
Se aplica el algoritmo de multiplicación por columnas. Cada dígito del primer número se multiplica por cada dígito del segundo, y el resultado se acumula en la posición correspondiente (i+j).
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s1, s2;
cin >> s1 >> s2;
int len1 = s1.size(), len2 = s2.size();
int result_len = len1 + len2;
int a[len1] = {}, b[len2] = {}, res[result_len] = {};
// Inversión y conversión a dígitos
for (int i = 0; i < len1; ++i)
a[len1 - 1 - i] = s1[i] - '0';
for (int i = 0; i < len2; ++i)
b[len2 - 1 - i] = s2[i] - '0';
// Multiplicación por columnas
for (int i = 0; i < len1; ++i) {
int carry = 0;
for (int j = 0; j < len2; ++j) {
res[i + j] += a[i] * b[j] + carry;
carry = res[i + j] / 10;
res[i + j] %= 10;
}
res[i + len2] = carry;
}
// Eliminar ceros iniciales
while (result_len > 1 && res[result_len - 1] == 0)
--result_len;
// Imprimir resultado en orden correcto
for (int i = result_len - 1; i >= 0; --i)
cout << res[i];
return 0;
}
2.4 División por Entero Pequeño
Este caso permite dividir un número grande entre un entero de bajo rango (por ejemplo, hasta 1000). Se simula el método de división larga: se toma un dígito a la vez, se forma el cociente parcial y se leva el residuo.
#include <iostream>
#include <string>
using namespace std;
int main() {
string large_num;
int divisor;
cin >> large_num >> divisor;
int len = large_num.size();
int digits[len + 1] = {}, quotient[len + 1] = {};
// Convertir cadena a dígitos (desde el inicio)
for (int i = 0; i < len; ++i)
digits[i + 1] = large_num[i] - '0';
int remainder = 0;
for (int i = 1; i <= len; ++i) {
int current = remainder * 10 + digits[i];
quotient[i] = current / divisor;
remainder = current % divisor;
}
// Eliminar ceros iniciales
int q_len = 1;
while (q_len < len && quotient[q_len] == 0)
++q_len;
for (int i = q_len; i <= len; ++i)
cout << quotient[i];
return 0;
}
- Conclusión
Las operaciones de alta precisión permiten trabajar con números que superan los límites de los tipos de datos nativos. Aunque el código puede parecer complejo, su lógica se basa en principios matemáticos fundamentales. Este enfoque es esencial en competencias de programación, criptografía y sistemas financieros.