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ódigoSubjectPor qué
#pragma onceQue el .hpp no se incluya dos veces.
#include <iostream>printable with the << operatorstd::ostream para el << que imprime.
#include <string>storing an array or a stringGuardo 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 bigintCreate a class called bigintLa clase.
{
private:El texto solo lo toca la propia clase.
std::string s;store an arbitrary precision unsigned integerLos 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 classTodo 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)additionSigo 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 + bUno 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ódigoSubjectPor qué
#include "bigint.hpp"Expected files : bigint.hpp, bigint.cppEl .cpp es obligatorio, pero todo está en el .hpp: basta con incluirlo.