bigint · Multi line
▶ Aprender bigint (Multi line) paso a paso · explicación de bigint
Otras versiones: One line · Cristi
Código línea a línea
Tres columnas: el código, el trozo del subject o del main que obliga a escribir esa línea, y el por qué.
bigint.hpp
| Código | Subject | Por qué |
|---|---|---|
#pragma once | Que el .hpp no se incluya dos veces. | |
| ||
#include <iostream> | printable with the << operator | std::ostream para el << que imprime. |
#include <string> | storing an array or a string | Guardo el número como texto. |
#include <sstream> | std::ostringstream: pasar el unsigned int del constructor a texto. | |
#include <cstdlib> | std::strtoul: pasar el texto de un bigint a número para desplazar. | |
| ||
class bigint | Create a class called bigint | La clase. |
{ | ||
private: | El texto solo lo toca la propia clase. | |
std::string s; | store an arbitrary precision unsigned integer | Los dígitos como texto: 1337 → "1337". Cabe cualquier tamaño. Sin signo = nunca negativo. |
| ||
public: | You will find a main in this directory that must work with your class | Todo lo que usa el main. |
// ---------- forma canónica ---------- | ||
bigint() : s("0") {} | bigint b(21), c, d(1337), e(d); | c sin nada vale 0 → "0", no "" (si no, c no imprimiría nada). |
bigint(unsigned int n) | const bigint a(42);((b << 10) + 42) | Desde un número. Sin explicit: así el 42 suelto se convierte en bigint solo. |
{ | ||
std::ostringstream os; | Un "cout" que escribe en un texto. | |
os << n; | Escribo el número dentro. | |
s = os.str(); | Y saco el texto: 42 → "42". | |
} | ||
bigint(const bigint& o) : s(o.s) {} | e(d) | Copia: copio el texto. |
bigint& operator=(const bigint& o) | Forma canónica. Me cambia → sin const; me devuelvo a mí → bigint &. | |
{ | ||
s = o.s; | Copio el texto. | |
return *this; | Me devuelvo a mí. | |
} | ||
~bigint() {} | Destructor vacío: el string se libera solo. | |
| ||
// ---------- + ---------- | ||
bigint& operator+=(const bigint& o) | addition(c += a) | Aquí va la suma de verdad. Me cambia y me devuelvo a mí → bigint &. |
{ | ||
std::string r; | El resultado, vacío. Se llena por delante. | |
int i = s.size() - 1; | Último dígito mío (las unidades). | |
int j = o.s.size() - 1; | Último dígito del otro. | |
int carry = 0; | "Me llevo": empieza en 0. | |
while (i >= 0 || j >= 0 || carry) | addition | Sigo mientras me queden dígitos a mí, al otro, o me lleve algo (99 + 1 = 100). |
{ | ||
int sum = carry; | Empiezo con lo que me llevaba. | |
if (i >= 0) | Si aún me quedan dígitos… | |
sum += s[i--] - '0'; | …sumo el mío. - '0' pasa el carácter '7' al número 7. Luego i retrocede. | |
if (j >= 0) | Igual con el otro. | |
sum += o.s[j--] - '0'; | Sumo el suyo. | |
r.insert(r.begin(), char('0' + sum % 10)); | El dígito que toca (% 10), de vuelta a carácter, delante del resultado. | |
carry = sum / 10; | Lo que me llevo (0 o 1). | |
} | ||
s = r; | Me quedo con el resultado. | |
return *this; | Me devuelvo a mí. | |
} | ||
bigint operator+(const bigint& o) const | a + b | Uno nuevo → bigint. Solo miro → const (a es const). |
{ | ||
bigint t(*this); | Una copia de mí: a mí no me toco. | |
return t += o; | Le sumo a la copia y la devuelvo. Reutiliza +=. | |
} | ||
bigint& operator++() | ++b | ++b: me sumo 1 y me devuelvo a mí. |
{ | ||
return *this += 1; | El 1 se convierte en bigint solo. | |
} | ||
bigint operator++(int) | b++ | b++: me cambia pero devuelve cómo era antes → bigint. (int) solo distingue. |
{ | ||
bigint t(*this); | Una copia de mí: a mí no me toco. | |
++(*this); | Me sumo con el ++ de antes. | |
return t; | Devuelvo la copia vieja. | |
} | ||
| ||
// ---------- << ---------- | ||
bigint& operator<<=(const bigint& n) | "digitshift"(d <<= 4) | Me cambia y me devuelvo a mí. Recibe un bigint: el 4 se convierte solo. |
{ | ||
if (s != "0") | the output should not contain any leading zeros | Si valgo 0, desplazar sigue siendo 0: nada de "000". |
s.append(std::strtoul(n.s.c_str(), 0, 10), '0'); | (42 << 3 == 42000) | k ceros al final. k = el texto de n pasado a número. |
return *this; | Me devuelvo a mí. | |
} | ||
bigint operator<<(const bigint& n) const | (42 << 3 == 42000)((b << 10) + 42) | Uno nuevo, solo miro → const. |
{ | ||
bigint t(*this); | Una copia de mí: a mí no me toco. | |
return t <<= n; | Desplazo la copia y la devuelvo. | |
} | ||
| ||
// ---------- >> ---------- | ||
bigint& operator>>=(const bigint& n) | (1337 >> 2 == 13)(d >>= (const bigint)2) | Me cambia y me devuelvo a mí. El main pasa un bigint → const bigint &. |
{ | ||
size_t k = std::strtoul(n.s.c_str(), 0, 10); | Cuántos dígitos: el texto de n pasado a número. | |
if (k >= s.size()) | ¿Quito todos o más de los que tengo? | |
s = "0"; | Entonces queda 0. | |
else | ||
s.erase(s.size() - k); | (1337 >> 2 == 13) | Si no, borro desde la posición size - k hasta el final. |
return *this; | Me devuelvo a mí. | |
} | ||
bigint operator>>(const bigint& n) const | (1337 >> 2 == 13) | Uno nuevo, solo miro → const. |
{ | ||
bigint t(*this); | Una copia de mí: a mí no me toco. | |
return t >>= n; | Desplazo la copia y la devuelvo. | |
} | ||
| ||
// ---------- comparaciones ---------- | ||
bool operator==(const bigint& o) const | comparison(d == a) | Sí/no → bool. Solo miro → const. |
{ | ||
return s == o.s; | Mismo texto = mismo número. | |
} | ||
bool operator<(const bigint& o) const | (d < a) | Sí/no → bool. Solo miro → const. |
{ | ||
if (s.size() != o.s.size()) | Como texto "9" > "10", pero como número no: primero la longitud. | |
return s.size() < o.s.size(); | Menos dígitos = menor. | |
return s < o.s; | Misma longitud: el texto se compara igual que el número. | |
} | ||
bool operator!=(const bigint& o) const | (d != a) | Lo contrario de ==. |
{ | ||
return !(*this == o); | Reutilizo ==. | |
} | ||
bool operator>(const bigint& o) const | (d > a) | a > b es b < a. |
{ | ||
return o < *this; | Le doy la vuelta y uso <. | |
} | ||
bool operator<=(const bigint& o) const | (d <= a) | a <= b es "no b < a". |
{ | ||
return !(o < *this); | ||
} | ||
bool operator>=(const bigint& o) const | (d >= a) | a >= b es "no a < b". |
{ | ||
return !(*this < o); | ||
} | ||
| ||
// ---------- cout << ---------- | ||
friend std::ostream& operator<<(std::ostream& os, const bigint& b) | printable with the << operator (in base 10)std::cout << "a = " << a << std::endl; | El << que imprime: a la izquierda está cout → friend. const bigint & para imprimir a. |
{ | ||
return os << b.s; | Escribo el texto en os y devuelvo os. | |
} | ||
}; |
bigint.cpp
| Código | Subject | Por qué |
|---|---|---|
#include "bigint.hpp" | Expected files : bigint.hpp, bigint.cpp | El .cpp es obligatorio, pero todo está en el .hpp: basta con incluirlo. |