El número más grande en C

4 minutos de lectura

avatar de usuario
usuario2416353

scanf("%d",&a);
for(b=1;b<=a;++b)
{
    c*=b;
}
printf("%lu",c);

¡Quiero obtener la respuesta de 100!
factorial de 100. ¿cómo puedo obtener esto? (Quiero obtener un mayor rango de números) ¿No podemos tener el límite de números hasta el infinito?

  • Entonces, ¿cuál es el punto de c# y java etiquetas?

    – Soner Gonül

    11 de junio de 2013 a las 6:37

  • Suponiendo que usa C#, puede leer la respuesta aquí. En Java puedes usar java.math.BigInteger.

    – Uwe Plonus

    11 de junio de 2013 a las 6:38

  • No puede tener un rango entero infinito, porque su computadora no tiene memoria infinita para almacenarlo.

    –Daniel Kamil Kozar

    11 de junio de 2013 a las 6:43

  • 100! = 9332621544394415268169923885626670049071596826438162146859 29638952175999932299156089414639761565182862536979208272237582511852109168 64000000000000000000000000. Me lo dio el código en la respuesta de BLUEPIXY y verificado.

    usuario2088790

    11 de junio de 2013 a las 13:07

avatar de usuario
Yuushi

El rango máximo de enteros es, en casi todas las plataformas (modernas), 2^31 - 1 (aunque, por norma, int solo se requiere que tenga al menos 16 bits). Para su plataforma determinada, se definirá como INT_MAX en <limits.h>.

100! obviamente superará con creces esto. Para calcular algo tan grande en Cnecesitará una gran biblioteca de enteros, como BPF.

Solo como nota de advertencia, si decide probar y usar un double (que puede contener números de este tamaño), obtendrá una respuesta incorrecta debido a la pérdida de precisión. Esto es fácil de detectar: ​​en mi máquina, los últimos dígitos son 48que obviamente es una tontería: 100! debe ser divisible por 100, por lo tanto debe tener 00 como los dos últimos dígitos.

  • puede en realidad calcularlo sin usar la biblioteca GMP. PostgreSQL admite aritmética de enteros de precisión ilimitada. El valor exacto está aquí: sqlfiddle.com/#!12/d41d8/991

    – jugador más valioso

    11 de junio de 2013 a las 7:08

  • @mvp ¿Qué tiene eso que ver con poder calcularlo en C? Puede calcularlo en Python, Lisp, Haskell, Java, C#. Nada de eso significa ponerse en cuclillas si está limitado a C.

    – Yuushi

    11 de junio de 2013 a las 7:10

  • Solo me estaba divirtiendo. Y, por cierto, PostgreSQL está escrito en C. Por lo tanto, puede extraer funciones de precisión ilimitadas de su fuente.

    – jugador más valioso

    11 de junio de 2013 a las 7:12

  • En realidad termina en 000000000000000000000000

    usuario2088790

    11 de junio de 2013 a las 13:09

avatar de usuario
AZULPIXY

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#if __STDC_VERSION__>=199901L
#include <inttypes.h>
#else
#define PRIu16 "hu"
#endif

typedef struct _unums {
    size_t size;
    uint16_t *nums;//array 
} UNums;

void UNums_init(UNums *num, uint16_t n){
    num->nums = (uint16_t*)malloc(sizeof(uint16_t));
    num->nums[0] = n;
    num->size = 1;
}

void UNums_mul(UNums *num, uint16_t n){
    uint16_t carry = 0;
    size_t i;

    for(i=0;i<num->size;++i){
        uint32_t wk = n;
        wk = wk * num->nums[i] + carry;
        num->nums[i] = wk % 10000;
        carry = wk / 10000;
    }
    if(carry){
        num->size += 1;
        num->nums = (uint16_t*)realloc(num->nums, num->size * sizeof(uint16_t));
        num->nums[i] = carry;
    }
}

void UNums_print(UNums *num){
    size_t i = num->size;
    int w = 0;
    do{
        --i;
        printf("%0*" PRIu16, w, num->nums[i]);
        if(!w) w = 4;
    }while(i!=0);
}

void UNum_drop(UNums *num){
    free(num->nums);
    num->nums = NULL;
}

int main( void ){
    UNums n;
    uint16_t i;

    UNums_init(&n, 1);
    for(i=2;i<=100;++i)
        UNums_mul(&n, i);
    UNums_print(&n);//100!
    UNum_drop(&n);
    return 0;
}

  • Lástima que Visual Studio no tiene inttypes.h

    usuario2088790

    11 de junio de 2013 a las 9:44

  • ¡Gracias! Lo hice funcionar, tuve que encasillar las funciones malloc y realloc también.

    usuario2088790

    11 de junio de 2013 a las 13:03

  • @raxman Se compilará en C++. No hay necesidad de lanzar C. Pero me fijaron bien como bueno. Gracias.

    – PIXY AZUL

    11 de junio de 2013 a las 13:18


  • Oh, ya veo, esta es una pregunta/respuesta estrictamente C.

    usuario2088790

    11 de junio de 2013 a las 13:20

  • respuesta encantadora: ¡quién dice que no puedes obtener números grandes en unas pocas líneas de C!

    – usuario4815162342

    11 de junio de 2013 a las 14:17


avatar de usuario
Thanushan

Para números pequeños es mejor usar unsigned long long que int. Pero aún tiene un límite en el número más grande que puede usar para a. Tu podrías intentar double o float pero es posible que obtenga un error de precesión.

Puedes usar biblioteca GMP

Instalar con:

sudo apt-get install libgmp3-dev

C Principal:

#include <gmp.h>

void f() tooBigForYourShell {
    mpz_t n;                     // declare a big n number
    mpz_init_set_ui(n,0);        // assign 0 as starting value
    mpz_setbit(n, 1UL << 24);    // set bit 2^24 (index 2^24 and not 24...) as 1.
    gmp_printf("%Zd\n", n);      // display the result
}

int main() {
    tooBigForYourShell();
    return 0;
}

Compilar con:

gcc main.c -lgmp && ./a.out
???
profit, enjoy your 2^(2^24) number on stdout.

ingrese la descripción de la imagen aquí
NB: Hay muchos más dígitos antes…

Tú podrías teóricamente suba a 37 bits usados ​​(entonces 2^38 – 1 ?) pero tenga cuidado ya que usará una gran cantidad de su CPU.

/!\ NO SOY RESPONSABLE DE NINGÚN DAÑO SI USTED OPTA POR 2^(2^37).

¿Ha sido útil esta solución?