bigint · One line
▶ Aprender bigint (One line) paso a paso · explicación de bigint
Otras versiones: Multi 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) { std::ostringstream os; os << n; s = os.str(); } | const bigint a(42);((b << 10) + 42) | Desde un número: lo escribo en un ostringstream y saco el texto. Sin explicit: así el 42 suelto se convierte en bigint solo. |
bigint(const bigint& o) : s(o.s) {} | e(d) | Copia: copio el texto. |
bigint& operator=(const bigint& o) { s = o.s; return *this; } | Forma canónica. Me cambia → sin const; me devuelvo a mí → bigint &. | |
~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 { bigint t(*this); return t += o; } | a + b | Uno nuevo → bigint. Solo miro → const (a es const). Copia de mí + +=. |
bigint& operator++() { return *this += 1; } | ++b | ++b: me sumo 1 (el 1 se convierte en bigint solo) y me devuelvo a mí. |
bigint operator++(int) { bigint t(*this); ++(*this); return t; } | b++ | b++: me cambia pero devuelve cómo era antes → bigint. (int) solo distingue. |
| ||
// ---------- << ---------- | ||
bigint& operator<<=(const bigint& n) { if (s != "0") s.append(std::strtoul(n.s.c_str(), 0, 10), '0'); return *this; } | "digitshift" (42 << 3 == 42000) (d <<= 4) | Añado k ceros al final. Si valgo 0 no añado nada (si no, "000"). k sale del texto de n con strtoul. |
bigint operator<<(const bigint& n) const { bigint t(*this); return t <<= n; } | (42 << 3 == 42000)((b << 10) + 42) | Uno nuevo: copia de mí + <<=. |
| ||
// ---------- >> ---------- | ||
bigint& operator>>=(const bigint& n) { size_t k = std::strtoul(n.s.c_str(), 0, 10); if (k >= s.size()) s = "0"; else s.erase(s.size() - k); return *this; } | (1337 >> 2 == 13)(d >>= (const bigint)2) | Quito k dígitos del final. Si quito todos o más → "0". |
bigint operator>>(const bigint& n) const { bigint t(*this); return t >>= n; } | (1337 >> 2 == 13) | Uno nuevo: copia de mí + >>=. |
| ||
// ---------- comparaciones ---------- | ||
bool operator==(const bigint& o) const { return s == o.s; } | comparison(d == a) | Sin ceros delante, dos números son iguales si su texto es igual. |
bool operator<(const bigint& o) const { if (s.size() != o.s.size()) return s.size() < o.s.size(); return s < o.s; } | (d < a) | Primero la longitud: menos dígitos = menor. Con la misma, vale comparar el texto. |
bool operator!=(const bigint& o) const { return !(*this == o); } | (d != a) | Lo contrario de ==. |
bool operator>(const bigint& o) const { return o < *this; } | (d > a) | a > b es b < a. |
bool operator<=(const bigint& o) const { return !(o < *this); } | (d <= a) | a <= b es "no b < a". |
bool operator>=(const bigint& o) const { return !(*this < o); } | (d >= a) | a >= b es "no a < b". |
| ||
// ---------- cout << ---------- | ||
friend std::ostream& operator<<(std::ostream& os, const bigint& b) { return os << b.s; } | printable with the << operator (in base 10)std::cout << "a = " << a << std::endl; | El << que imprime: a la izquierda está cout → friend. Escribe mi texto en os y devuelve 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. |