2026-08-17 12:21:57 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Main.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza"
|
| | | #property link "https://www.mql5.com"
|
| | | #property strict
|
| | |
|
| | | #ifndef BIGNUMBERSBYLEO_SRC_UTILS_MAIN_MQH
|
| | | #define BIGNUMBERSBYLEO_SRC_UTILS_MAIN_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-26 22:31:33 -05:00 | | | #include <TSN\\Tables\\Bits.mqh>
|
2026-09-26 20:59:30 -05:00 | | | #include <TSN\\Tables\\Misce.mqh>
|
| | | #include <TSN\\MQLArticles\\Utils\\EncodeHex.mqh>
|
2026-08-26 22:31:33 -05:00 | | |
|
2026-08-17 12:21:57 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
2026-08-22 14:12:43 -05:00 | | | //+------------------------------------------------------------------+
|
2026-08-26 22:31:33 -05:00 | | | namespace TSN
|
| | | {
|
2026-08-22 14:12:43 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
2026-08-17 12:21:57 -05:00 | | | //+------------------------------------------------------------------+
|
| | | class CNumberUtils
|
| | | {
|
| | | public:
|
| | | CNumberUtils(void) {}
|
| | | ~CNumberUtils(void) {}
|
2026-08-19 11:09:16 -05:00 | | |
|
2026-08-26 22:31:33 -05:00 | | | //--- Divisiones (d algortim)
|
2026-08-21 13:18:06 -05:00 | | | static uint Div3by2(ulong a2, ulong a1, ulong a0, ulong v1, ulong v0, ulong &rem_out);
|
2026-08-21 21:01:14 -05:00 | | | static ulong Div128to64(ulong hi, ulong lo, ulong d, ulong& res);
|
| | |
|
| | | //--- mul 64*64
|
| | | static void Mul64to128(const ulong a, const ulong b, ulong &hi, ulong &lo);
|
2026-08-26 22:31:33 -05:00 | | |
|
2026-08-27 10:22:04 -05:00 | | | //--- To Bytes (numeros basicos - nativos de mt5 o structs con CLZ cargado para ellos..)
|
2026-08-26 22:31:33 -05:00 | | | template <typename TNumber>
|
| | | static int SValueToBytesBE(const TNumber value, uchar& buf[], int w = 0, int k = -1);
|
| | | template <typename TNumber>
|
| | | static int SValueToBytesLE(const TNumber value, uchar& buf[], int w = 0, int k = -1);
|
2026-09-02 07:23:09 -05:00 | | |
|
| | | //--- from bytes (se leen sizeof(bytes) exactos)
|
| | | template <typename TNumber>
|
| | | static int SVAlaueFromBytesBE(TNumber& value, const uchar& buf[], int r = 0);
|
2026-09-03 19:55:01 -05:00 | | |
|
| | |
|
| | | //--- utilidades para ulong.. en especifico (big numebrs)
|
| | | static void ULL_LoadFromBytesBE(const int k, ulong& m_v[], int& m_v_s, const uchar& buf[], int& j);
|
| | | static void ULL_LoadFromBytesLE(const int k, ulong& m_v[], int& m_v_s, const uchar& buf[], int& j);
|
2026-09-11 09:36:42 -05:00 | | |
|
| | | //---
|
| | | static ulong ModInv(uint64_t a);
|
2026-08-17 12:21:57 -05:00 | | | };
|
2026-08-19 11:09:16 -05:00 | | |
|
2026-09-03 19:55:01 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | static void CNumberUtils::ULL_LoadFromBytesLE(const int k, ulong &m_v[], int &m_v_s, const uchar &buf[], int& j)
|
| | | {
|
| | | //---
|
| | | const int sob = k & 7; // % 8 cuantos sobraan
|
| | | const int blocks = k - sob; // Cuantos bloques enteros procesaremos
|
| | |
|
| | | //--- Ahora si
|
| | | m_v_s = 0;
|
| | | int r = 0;
|
| | | // bloques completos
|
| | | for(; r < blocks;)
|
| | | {
|
| | | //--- write
|
| | | m_v[m_v_s++] = ulong(buf[r++]) |
|
| | | ulong(buf[r++]) << 8 |
|
| | | ulong(buf[r++]) << 16 |
|
| | | ulong(buf[r++]) << 24 |
|
| | | ulong(buf[r++]) << 32 |
|
| | | ulong(buf[r++]) << 40 |
|
| | | ulong(buf[r++]) << 48 |
|
| | | ulong(buf[r++]) << 56;
|
| | | }
|
| | | // en caso haya sobrante
|
| | | if(sob)
|
| | | {
|
| | | m_v[m_v_s] = 0ULL;
|
| | | for(j = 0; j < (sob << 3); j += 8)
|
| | | m_v[m_v_s] |= ulong(buf[r++]) << j;
|
| | | m_v_s++;
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | static void CNumberUtils::ULL_LoadFromBytesBE(const int k, ulong &m_v[], int &m_v_s, const uchar &buf[], int& j)
|
| | | {
|
| | | //---
|
| | | const int sob = k & 7; // % 8 cuantos sobraan
|
| | | const int blocks = k - sob; // Cuantos bloques enteros procesaremos
|
| | |
|
| | | //--- Ahora si
|
| | | int r = blocks - 1;
|
| | | m_v_s = 0;
|
| | | // bloques completos
|
| | | for(; r >= 0;)
|
| | | {
|
| | | //--- write
|
| | | m_v[m_v_s++] = ulong(buf[r--]) |
|
| | | ulong(buf[r--]) << 8 |
|
| | | ulong(buf[r--]) << 16 |
|
| | | ulong(buf[r--]) << 24 |
|
| | | ulong(buf[r--]) << 32 |
|
| | | ulong(buf[r--]) << 40 |
|
| | | ulong(buf[r--]) << 48 |
|
| | | ulong(buf[r--]) << 56;
|
| | | }
|
| | | // en caso haya sobrante
|
| | | if(sob)
|
| | | {
|
| | | r = sob - 1; // reinicamos dado qeu peude ser (-1)
|
| | | m_v[m_v_s] = 0ULL;
|
| | | for(j = 0; j < (sob << 3); j += 8)
|
| | | m_v[m_v_s] |= ulong(buf[r--]) << j;
|
| | | m_v_s++;
|
| | | }
|
| | | }
|
| | |
|
2026-08-26 22:31:33 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
2026-08-27 10:22:04 -05:00 | | | //+------------------------------------------------------------------+
|
| | | #define NUMBERUTILS_VALUEBYTES_EXACT (-2)
|
| | | #define NUMBERUTILS_VALUEBYTES_FULL (-1)
|
| | |
|
2026-08-26 22:31:33 -05:00 | | | //+------------------------------------------------------------------+
|
| | | template <typename TNumber>
|
| | | static int CNumberUtils::SValueToBytesLE(const TNumber value, uchar &buf[], int w = 0, int k = -1)
|
| | | {
|
| | | //---
|
2026-08-27 10:22:04 -05:00 | | | if(k == -2)
|
| | | {
|
2026-08-29 11:36:58 -05:00 | | | k = sizeof(TNumber) - (CBitTricks::CLZ(value) >> 3);
|
2026-08-27 10:22:04 -05:00 | | | }
|
| | | else
|
| | | if(k == -1)
|
| | | k = sizeof(TNumber);
|
| | |
|
2026-08-26 22:31:33 -05:00 | | | //---
|
| | | if(k + w > ArraySize(buf))
|
| | | ArrayResize(buf, k + w);
|
| | |
|
| | | //---
|
| | | union U
|
| | | {
|
| | | uchar bytes[sizeof(TNumber)];
|
| | | TNumber value;
|
| | | } rp;
|
| | | rp.value = value;
|
| | |
|
| | | //---
|
| | | for(int i = 0; i < k; i++)
|
| | | buf[w++] = rp.bytes[i];
|
| | |
|
| | | //---
|
| | | return w;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TNumber>
|
| | | static int CNumberUtils::SValueToBytesBE(const TNumber value, uchar &buf[], int w = 0, int k = -1)
|
| | | {
|
| | | //---
|
| | | if(k == -2)
|
| | | {
|
2026-08-29 11:36:58 -05:00 | | | k = sizeof(TNumber) - (CBitTricks::CLZ(value) >> 3);
|
2026-08-26 22:31:33 -05:00 | | | }
|
2026-08-27 10:22:04 -05:00 | | | else
|
| | | if(k == -1)
|
| | | k = sizeof(TNumber);
|
| | |
|
2026-08-26 22:31:33 -05:00 | | | //---
|
| | | if(k + w > ArraySize(buf))
|
| | | ArrayResize(buf, k + w);
|
| | |
|
| | | //---
|
| | | union U
|
| | | {
|
| | | uchar bytes[sizeof(TNumber)];
|
| | | TNumber value;
|
| | | } rp;
|
| | | rp.value = value;
|
| | |
|
| | | //---
|
| | | for(int i = k - 1; i >= 0; i--)
|
| | | buf[w++] = rp.bytes[i];
|
| | |
|
| | | //---
|
| | | return w;
|
| | | }
|
| | |
|
| | |
|
2026-09-02 07:23:09 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TNumber>
|
| | | static int CNumberUtils::SVAlaueFromBytesBE(TNumber &value, const uchar &buf[], int r = 0)
|
| | | {
|
| | | value = 0;
|
2026-09-03 19:55:01 -05:00 | | | // el byte mas signicvas lo ponemos al mas alto del numero .. y asi
|
| | | // y el menos signicaid (mas adelnte) ira en lso bajos del numero
|
2026-09-02 07:23:09 -05:00 | | | for(int i = ((sizeof(TNumber) - 1) << 3) ; i >= 0; i -= 8)
|
| | | {
|
| | | value |= buf[r++] << i;
|
| | | }
|
| | | return r;
|
| | | }
|
| | |
|
2026-08-21 21:01:14 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #define NUMBERUTILS_BASE_ALG(LO, HI) \
|
| | | const ulong lo_lo = a_lo * b_lo; \
|
| | | const ulong hi_lo = a_hi * b_lo; \
|
| | | const ulong lo_hi = a_lo * b_hi; \
|
| | | const ulong hi_hi = a_hi * b_hi; \
|
| | | const ulong inter = (lo_lo >> 32) + (uint)hi_lo + (uint)lo_hi; \
|
| | | LO = (inter << 32) | (uint)lo_lo; \
|
| | | HI = hi_hi + (hi_lo >> 32) + (lo_hi >> 32) + (inter >> 32); \
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | static void CNumberUtils::Mul64to128(const ulong a, const ulong b, ulong &hi, ulong &lo)
|
| | | {
|
| | | //---
|
| | | const ulong a_lo = (uint)a;
|
| | | const ulong a_hi = a >> 32;
|
| | | const ulong b_lo = (uint)b;
|
| | | const ulong b_hi = b >> 32;
|
| | |
|
| | | //---
|
| | | NUMBERUTILS_BASE_ALG(lo, hi)
|
| | | }
|
| | |
|
2026-08-21 13:18:06 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #define NUMBERUTILS_BASE32_UL (4294967296ULL)
|
| | |
|
| | | //---
|
| | | // division de un numero de 96 bits entre uno de 64 bits
|
| | | // (pero tratamos a los numeors como base1<<32)
|
| | | // A = Dividoendo de 96 bits
|
| | | // V = Divisor de 64 bits
|
| | | static uint CNumberUtils::Div3by2(ulong a2, ulong a1, ulong a0, ulong v1, ulong v0, ulong &rem_out)
|
| | | {
|
| | | // parte alta del numero
|
| | | ulong num_hi = (a2 << 32) | a1;
|
| | |
|
| | | // ahora estimoas incialemtne
|
| | | ulong qhat;
|
| | | // Ahora neceismots veirica rque la division de los altos no haya oveflow (tome 2 digitos o mas)
|
| | | // Entonces tenemos esto
|
| | | // a2a1a0 | v1v0
|
| | | // sabemos primero que:
|
| | | // si:
|
| | | // a2 > v1
|
| | | // el cociente sera grande y peude que de overflow.. pero esto hasta cierto punto exactmnte el punto de quiereb es ==
|
| | | // de ahi en adlenteo con a2 < v1 entonces el reusltao cabe en un digito...
|
| | | // Como noosotros garantizamos que a2 <= v1 por tema de que el resto temrina siendo el hi
|
| | | // entonces solo nos queda comprar el unico caso de == en ese caso hay overflow.. o pued haberlo
|
| | | // Para ese caso en concreto tipo ab/a tomeos un caso borde tipo 49/4 = 12 (truncado)
|
| | | // ahi si pasa a mas de un digito el overflow seria de 10 % 10 = 2 seria el reusltado con overflow
|
| | | // lo cual se aleja mucho de 12 como resultado demasido
|
| | | // en cambio cno base-1 qeu es lo mas cercano a "base" que pódemos dar sin tener overflow tenemos un error de 3
|
| | | // por eso.. lo elegimos
|
| | | if(a2 == v1)
|
| | | qhat = NUMBERUTILS_BASE32_UL - 1;
|
| | | else
|
| | | qhat = num_hi / v1;
|
| | |
|
| | | // resto
|
| | | ulong rhat = num_hi - qhat * v1;
|
| | |
|
| | | // Ahora tenemos que corregir esa estimacion inicial qeu hicimos
|
| | | // dado qeu no tuvimos en caunto los bajos
|
| | | while(rhat < NUMBERUTILS_BASE32_UL && qhat * v0 > (rhat << 32) + a0)
|
| | | {
|
| | | qhat--;
|
| | | rhat += v1;
|
| | | }
|
| | |
|
| | | // listo ahora si calculso el resto y el cociente finales
|
| | | // multiplces el cociente qhat por el diviosr...
|
| | | // a * b
|
| | | // a = qhat
|
| | | // b = full_v { (v1 << 32) | v0 } (V completo Divisor)
|
| | | ulong prod_hi, prod_lo;
|
| | | //--- mul64
|
| | | {
|
| | | //---
|
| | | const ulong a_lo = (uint)qhat; //
|
| | | const ulong a_hi = qhat >> 32;
|
| | |
|
| | | const ulong full_v = (v1 << 32) | v0;
|
| | | const ulong b_lo = (uint)full_v;
|
| | | const ulong b_hi = full_v >> 32;
|
| | |
|
| | | //---
|
2026-08-21 21:01:14 -05:00 | | | NUMBERUTILS_BASE_ALG(prod_lo, prod_hi)
|
2026-08-21 13:18:06 -05:00 | | | }
|
| | |
|
| | | // Ahora Recontruyanos el dividendo A
|
| | | ulong cur_hi = num_hi >> 32;
|
| | | ulong cur_lo = (num_hi << 32) | a0;
|
| | |
|
| | | // restemos (A - Qhat*Divisor)
|
| | | ulong r_hi, r_lo;
|
| | | //
|
| | | // Sub128(ulong cur_hi, ulong cur_lo, ulong prod_hi, ulong prod_lo, ulong & r_hi, ulong & r_lo)
|
| | | {
|
| | | r_lo = cur_lo - prod_lo; // resta baja
|
| | | //ulong borrow = (cur_lo < prod_lo); en caso sea menor hara overflow y neceismto quitarle a la resta alta.. eso
|
| | | r_hi = cur_hi - prod_hi - (cur_lo < prod_lo);
|
| | | }
|
| | | // resto final (rhi como tal deberia de ser 0 por que a2<=v1)
|
| | | rem_out = r_lo;
|
| | | // cociente
|
| | | return (uint)qhat;
|
| | | }
|
| | |
|
2026-08-19 11:09:16 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // hi=64,lo=64 dividendo de 128 bits
|
2026-08-21 21:01:14 -05:00 | | | // d=64 divisor
|
2026-08-19 11:09:16 -05:00 | | | // res=resto
|
| | | //---
|
2026-08-21 21:01:14 -05:00 | | | static ulong CNumberUtils::Div128to64(ulong hi, ulong lo, ulong d, ulong &res)
|
2026-08-19 11:09:16 -05:00 | | | {
|
| | | //---
|
2026-08-21 21:01:14 -05:00 | | | if(d == 0)
|
2026-08-19 11:09:16 -05:00 | | | {
|
| | | // division por 0
|
| | | res = 0;
|
| | | return 0;
|
| | | }
|
| | | //---
|
| | | // aqui no chekeamos si hi no es 0 dado qeu el uso de esta funcion ya se hace eso previo
|
| | | // if (hi==0)
|
| | |
|
| | | //--- Normalizacion
|
| | | // Aqui la idea es "agrandar" los numeros
|
| | | // la idea es que el algoritmo que utilizamos toma 2 digitios de del diviendo y los divide entre los altos del divisor
|
| | | // luego con eso tenemos una esitmacion que corregiremos
|
| | | // Esto funcioona como estimacion daod que si lo piensas
|
| | | /*
|
| | | Si didivdes digmoas te daras cuenta que si logras dividr los altos te da algo aproximado de lo qeu puede ser el resutlado
|
| | | Por ejemplo aqui si dividies 100 /3 te da 33 una estimacion inicial.. pero oviamtne en el algoritmoi
|
| | | solo podemos diividr 1/1 diogito asi que se hace una estimacion mas simple de sumar ambos digitios
|
| | | y didviddr
|
| | | 153 | 3
|
| | | */
|
| | | // Eso creo que es en parte luego deshemamos este escaldo de los datos
|
| | | // Lo que si es que esto sirve para poder ejeuctar el algoritmo.. y simplifcair pasos y hacerlo mas rpaido
|
| | | // y hacer que funcione esa esitmacion de tomar los atlos para estimar y corregir
|
| | | //---
|
| | | // Esto tambein es parte de el aglritmo de kruth, esto{ D=(B / L + 1) }
|
| | | // pero hecho para div 128/64
|
| | | // La idea es cumplir con >=b/2 b = 1<<64
|
| | | // osea >= 1<<63 el minimo candidoa que cumple esto es 0x8000000000000000
|
| | | // (100000000000....0) en binario... de ahi en adlente cumple
|
| | | // asi que shifteamos el divisor hasta que tenga ese valor
|
| | | int shift = 0; // cuants veces shiftemosa
|
| | | while((d & 0x8000000000000000) == 0) // buscamos que el mas alto este activo
|
| | | {
|
| | | // si no lo esta vamos dezplazando
|
| | | d <<= 1;
|
| | | shift++;
|
| | | }
|
| | | // una vez lo tenga tenemos que normalizar lo qeu qeuda
|
| | | ulong flow, hi_nor, lo_nor;
|
| | | // uflow = el desborde que hi (dado que como shifteamos peude desbordar)
|
| | | // hinor = hi normalizando
|
| | | // lonor = lo normlizado
|
| | | if(shift == 0) // ya estaba
|
| | | {
|
| | | hi_nor = hi;
|
| | | lo_nor = lo;
|
| | | flow = 0; // nada
|
| | | }
|
| | | else
|
| | | {
|
| | | // si dezplazamos
|
2026-08-19 21:36:19 -05:00 | | |
|
2026-08-19 11:09:16 -05:00 | | | // los altos que salen
|
| | | const int shr = 64 - shift;
|
2026-08-19 21:36:19 -05:00 | | | flow = (hi >> shr);
|
2026-08-19 11:09:16 -05:00 | | | // hi = [.....]
|
| | | // tomamos los shift mejhores
|
| | | // y los comabismo con el ov de lo
|
| | | // [....][....]
|
| | | // dezplaza << 2
|
| | | // [..][[..][.. de lo]][[..][se perdiuern]]
|
| | | hi_nor = (hi << shift) | (lo >> shr);
|
| | | lo_nor = lo << shift;
|
| | | }
|
| | | // normllzaicion hecha
|
| | |
|
| | | //--- Ahora si emepzamos la division
|
| | | // Ahora partimos todo
|
| | | // divisor en dos digitos
|
2026-08-21 13:18:06 -05:00 | | | const ulong d_hi = d >> 32;
|
| | | const ulong d_lo = d & 0xFFFFFFFF;
|
2026-08-19 11:09:16 -05:00 | | |
|
| | | // dividendo = [flow | hi_n | lo_n]
|
2026-08-21 13:18:06 -05:00 | | | const ulong dividendo_3 = hi_nor >> 32;
|
| | | const ulong dividendo_2 = hi_nor & 0xFFFFFFFF;
|
| | | const ulong dividendo_1 = lo_nor >> 32;
|
| | | const ulong dividendo_0 = lo_nor & 0xFFFFFFFF;
|
| | |
|
| | | //---- main
|
| | | // La idea es ir diviendo como en esuclo de mayot a menor e ir bajaando restos
|
| | | ulong r_hi = 0, r_lo = 0;
|
| | | uint q4, q3, q2, q1, q0;
|
| | | ulong rem;
|
| | |
|
| | | /*
|
| | | flow dividendo_3 dividendo_2 dividendo_1 dividendo_0 | d_hi d_lo
|
| | | ----------
|
| | |
|
| | | 1.
|
| | | Dividors
|
| | |
|
| | | rlo rhi flow entre dhi y dlo (parte alta)
|
| | |
|
| | |
|
| | | */
|
| | |
|
| | | //---
|
| | | q4 = Div3by2(r_hi, r_lo, flow, d_hi, d_lo, rem);
|
| | | r_hi = rem >> 32;
|
| | | r_lo = rem & 0xFFFFFFFF;
|
2026-08-19 11:09:16 -05:00 | | |
|
2026-08-21 13:18:06 -05:00 | | |
|
| | | //---
|
| | | q3 = Div3by2(r_hi, r_lo, dividendo_3, d_hi, d_lo, rem);
|
| | | r_hi = rem >> 32;
|
| | | r_lo = rem & 0xFFFFFFFF;
|
| | |
|
| | |
|
| | | //---
|
| | | q2 = Div3by2(r_hi, r_lo, dividendo_2, d_hi, d_lo, rem);
|
| | | r_hi = rem >> 32;
|
| | | r_lo = rem & 0xFFFFFFFF;
|
| | |
|
| | |
|
| | | //---
|
| | | q1 = Div3by2(r_hi, r_lo, dividendo_1, d_hi, d_lo, rem);
|
| | | r_hi = rem >> 32;
|
| | | r_lo = rem & 0xFFFFFFFF;
|
| | |
|
| | |
|
| | | //---
|
| | | q0 = Div3by2(r_hi, r_lo, dividendo_0, d_hi, d_lo, rem);
|
| | | r_hi = rem >> 32;
|
| | | r_lo = rem & 0xFFFFFFFF;
|
| | |
|
| | |
|
| | | //---
|
| | | // solo tomoas q1 y q0 (pro el tema de divisor > HI el resultado siempre cabra en 2 digitos)
|
| | | const ulong cociente = ((ulong)q1 << 32) | (ulong)q0; // Q = q1*2^32 + q0
|
| | | // ahoramos el resto full
|
| | | const ulong resto_full = (r_hi << 32) | r_lo;
|
| | | // ahora normalizamos
|
| | | res = (shift == 0) ? resto_full : (resto_full >> shift);
|
2026-08-21 21:01:14 -05:00 | | | //---
|
| | | return cociente;
|
2026-08-19 21:36:19 -05:00 | | | }
|
2026-08-19 11:09:16 -05:00 | | |
|
2026-08-19 21:36:19 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-21 13:18:06 -05:00 | | | /*
|
| | | Un ejemplo internate del pro qeu esa noramllicion inincal es necesaira tomemos por ejemplo
|
| | | la diivison de 490/40
|
| | | Si vamos directo sin normlaizar tendmreos que
|
| | |
|
| | | qhat= 9 (4==4)
|
| | | rhat= (49 - (9*4)) = 49-36=13
|
| | |
|
| | | y aqui ya se ve el erro de como 13 que pasa por mucho el "2" que sepodia tener sin normalizar
|
| | | Y la division final todo ese proceso tambien se comntaine pro eelp el while no se corre (13<10 = false)
|
| | | luego ya se ausme qeu es correcto por lo que hace un mulde
|
| | | 9 * 40 (4 | 0) = 360
|
| | |
|
| | | luego
|
| | | cur_hi = 4
|
| | | curlo = 9 | 0
|
| | |
|
| | | y restamos
|
| | |
|
| | | (490 - 360) = 130
|
| | |
|
| | | se toma la parte baja (30)
|
| | | como resto=30
|
| | | y qhat seria el cocinente 9
|
| | | pero veriiando 9 * 30 = 270 esta super lejos de 490... error completo
|
| | |
|
| | | Ahora con la normaliacion previa
|
| | | nuestro factor D seria = (B / L+1) = 10 / 4+1 (L digitos mas singiacl del deivisor)
|
| | | osea D=2
|
| | |
|
| | | si escalamos
|
| | | 490*2=980
|
| | | 40*2=80
|
| | |
|
| | | ahora liuego
|
| | |
|
| | | qhat= 98/8 = 12 (aqui no es 9 adao que no son iguales)
|
| | | rhat= (98 - (12 * 8)) = 98 - 96 = 2 (justo se cumple la teroia que no pasa 2...)
|
| | |
|
| | | luego mul
|
| | | 12 * 80 = 960
|
| | |
|
| | | ahora si
|
| | | cur_hi = 9
|
| | | curlo=80
|
| | |
|
| | | 980 - 960 = 20
|
| | |
|
| | | con eso se temina y se cumple que R < Divisor asi que todo bien
|
| | | Por eso es improate el tema de la normlaciino, en caso sborde como este donde se lleva al limite esto
|
| | | nos topamos con este tipo de erorres que la aproxim de altos no da un reusltaod cercano
|
| | | como el caso que anlsiodnde ab0/a0
|
| | | Cero que pro eso esa aproxcim es util pro qeu noramlte cuiand divides numeros grandes el cociente por lo general es grande
|
| | | no hay peleas con devcimales ni nada y luego solo corriges y tiens algo bueno en cambio si lo hicieras
|
| | | sin onrlamliar te pelas con los deimcales enotnces creo que por ahi va el tema de la normalciion....
|
| | | */
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-09-11 09:36:42 -05:00 | | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | static ulong CNumberUtils::ModInv(ulong a)
|
| | | {
|
| | | /*
|
| | | https://ar5iv.labs.arxiv.org/html/1209.6626
|
| | | Este algoritmo lo saque estudiando como hacer la div exacta (esto luego se usara en gdc ext)...
|
| | | la idea es que partes de la igualdad general
|
| | | H(n+1) = Hn(2 - Hn)
|
| | | Que se usa para hallar el inverso con newton (partes de f(x) = 1\x - a = 0)
|
| | | la idea es eoncnotra ese x que satisficas, esto funcioan en relaes pero aqui trabajos en aritmetica mod
|
| | |
|
| | |
|
| | |
|
| | | U = (2-a) P (1+ (a-1)^2^i)
|
| | |
|
| | | - P = productorio
|
| | |
|
| | | - i terociamtne 6 pasos (numero minimo 2^6)
|
| | | pero en la practiva empezamos ya con 2-4 bits
|
| | | */
|
| | |
|
| | | uint64_t u = 2 - a;
|
| | | uint64_t curr = a - 1;
|
| | | // productorio
|
| | | for(int i = 0; i < 5; i++)
|
| | | {
|
| | | curr *= curr; // curr^2^i se eleva al cuadrado
|
| | | u *= curr + 1;
|
| | | }
|
| | | return u;
|
| | | }
|
| | |
|
2026-08-17 12:21:57 -05:00 | | | }
|
| | |
|
| | | #endif // BIGNUMBERSBYLEO_SRC_UTILS_MAIN_MQH
|