Resto de un numero natural de 200 digitos

Iniciado por WHK, 23 Agosto 2016, 01:47 AM

0 Miembros y 1 Visitante están viendo este tema.

WHK

Hola, alguien sabe de algún método para calcular el resto de un numero natural de 200 digitos?, he intentado con gmp pero no me da la longitud.

Saludos.

+ 1 Oculto(s)

no entiendo muy bien, pero parece interesante tu pregunta

_TTFH_3500

Cita de: WHK en 23 Agosto 2016, 01:47 AM
Hola, alguien sabe de algún método para calcular el resto de un numero natural de 200 digitos?, he intentado con gmp pero no me da la longitud.

Saludos.

Creo que hay una manera mirando las ultimas cifras pero no estoy seguro de como, por ejemplo


758412364598471254368451126 MOD 2 = 0

ya que el ultimo digito ('6') es par.

La gracia esta en que solo evaluas unos digitos en lugar de todo el número.


.rn3w.


WHK

Lo he logrado con php BC Math xD

http://php.net/manual/en/book.bc.php

Creo que gmp tiene un bug que no permite calcular la diferencia y resto de numeros mayores a 50 cifras, pero con bc math si pude :)

http://php.net/manual/en/function.bcmod.php

Eleкtro

#6
En .NET podrías haber utilizado la Class BigIntegers para realizar operaciones con números enteros:

Código (vbnet) [Seleccionar]
Dim bigInt1 As BigInteger = BigInteger.Parse(String.Format("1{0}", New String("0"c, count:=199)))
' 10000000000000000000000000000000000000000000000000
' 00000000000000000000000000000000000000000000000000
' 00000000000000000000000000000000000000000000000000
' 00000000000000000000000000000000000000000000000000

Dim sum As BigInteger = (bigInt1 + 1)
Dim rest As BigInteger = (bigInt1 - 1)
Dim divide As BigInteger = BigInteger.Divide(bigInt1, New BigInteger(2))
Dim remainder As BigInteger = (bigInt1 Mod divide)


En el código te muestro ejemplos muy básicos, de parsing, de instanciación de la class, de la capacidad de utilización de operadores aritméticos convencionales (+/- Mod/C#: %), y la utilización de métodos aritméticos de la class.

Saludos








.rn3w.


Eleкtro

#8
Cita de: -rn3w- en 23 Agosto 2016, 04:07 AMpero biginteger internamente es String

...No, en absoluto. BigIntegers no trabaja internamente con Strings, sino mayormente con arrays del tipo Byte (byte[]) como se puede verificar en el código fuente de la class BigInteger y BigNumber:

Obviamente el método BigIntegers.ToString() representará el valor en formato de texto, pues esa es la finalidad de cualquier método que lleve por nombre "ToString", del mismo modo que el método BigIntegers.Parse tomará como parámetro un valor de texto para parsear, pero ese aspecto no tiene nada que ver con el funcionamiento interno del algoritmo, sino con una de las formas que se le facilita al usuario final (el programador) para utilizar la class y representarla. Aparte, el constructor de la class expone varios overloads que aceptan otros datatypes distintos a String, entre ellos los datatypes numéricos convencionales y un array de Byte.

Saludos








class_OpenGL

Aquí dejo un programa que hice en C para un problema de Project Euler. El programa calcula la suma total de los dígitos de factorial de 200 (en realidad, el ejercicio pedía de 100, pero puse 200 para que tuviera más de 200 dígitos). En el programa, para obtener los dígitos, tengo que sacar el módulo, así que funciona correctamente (lo digo porque Project Euler dictaminó que mi respuesta era buena).

#include <stdlib.h>
#include <stdio.h>

typedef struct {
unsigned char *bytes;
unsigned int num_bytes;
} big_int;

void set_big_int(big_int *result, unsigned char number);
void multiply(big_int *result, unsigned char number);
void divide(big_int *result, unsigned char denominator);
unsigned char get_module(big_int *result, unsigned char denominator);
void factorial(big_int *result, unsigned char number);
int is_zero(big_int *big_integer);

int main() {
big_int big_integer = {NULL, 0};
unsigned char digit;
unsigned int num_digits = 0;
unsigned int result = 0;

fprintf(stdout, "Adding all digits of 200!...\n");

factorial(&big_integer, 200);

while(is_zero(&big_integer) == 0) {
num_digits++;

digit = get_module(&big_integer, 10);
fputc(digit + '0', stdout);
result += digit;

divide(&big_integer, 10);
}

fprintf(stdout, "\n\nDigit sum result: %u\n", result);
fprintf(stdout, "Number of digits: %u", num_digits);

fgetc(stdin);
return 0;
}

void set_big_int(big_int *result, unsigned char number) {
if(result->bytes != NULL)
free(result->bytes);

result->bytes = malloc(sizeof(unsigned char));
result->bytes[0] = number;
result->num_bytes = 1;
}

void multiply(big_int *result, unsigned char number) {
register int i;
unsigned int rest = 0;

for(i = 0; i < result->num_bytes; i++) {
rest = result->bytes[i] * number + rest;
result->bytes[i] = rest & 0x000000FF;
rest >>= 8;

if(rest != 0 && i+1 == result->num_bytes) {
result->num_bytes += 1;
realloc(result->bytes, result->num_bytes);
result->bytes[i+1] = 0;
}
}
}

void divide(big_int *result, unsigned char denominator) {
register int i;
unsigned int module = 0;
unsigned int new_size = result->num_bytes;

for(i = result->num_bytes-1; i >= 0; i--) {
module = (unsigned int)result->bytes[i] + (module << 8);
result->bytes[i] = module/denominator;
module %= denominator;
}

for(i = result->num_bytes-1; i >= 0 && result->bytes[i] == 0; i--)
new_size--;

if(new_size != result->num_bytes) {
result->num_bytes = new_size;
realloc(result->bytes, new_size);
}
}

unsigned char get_module(big_int *result, unsigned char denominator) {
register int i;
unsigned int module = 0;

for(i = result->num_bytes-1; i >= 0; i--)
module = ((unsigned int)result->bytes[i] + (module << 8))%denominator;

return module;
}

void factorial(big_int *result, unsigned char number) {
unsigned char i;

set_big_int(result, 1);
for(i = 2; i <= number; i++)
multiply(result, i);
}

int is_zero(big_int *big_integer) {
register unsigned int i;
unsigned int result = 1;

for(i = 0; result == 1 && i < big_integer->num_bytes; i++)
result = big_integer->bytes[i] == 0;

return result;
}


Además, le he agregado para que imprima los dígitos en Little Endian, así que la salida del programa para calcular el factorial de 200 sería...

00000000000000000000000000000000000000000000000002747379830732698722222987169785
80071532604230714091306220668659755047521230423093757042424257723584928247221314
68192330452042466154126544229349889693732713367072758264311139928259426629160501
73624209724675203883691983121277140932648911048240302924330436994495344233524749
2362371786779531592260581239312363255305097463768756887

Digit sum result: 1404
Number of digits: 375

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL