Valore maggiore di un unsigned long long int

di Anonimizzato28223 il
5 risposte
Salve a tutti,

Sto provando a risolvere questo esercizio:
We need to sum big numbers and we require your help.
Write a function that returns the sum of two numbers. The input numbers are strings and the function must return a string.
Io ho scritto questo codice
#include <stdlib.h>
#include <stdio.h>

char *add(const char *a, const char *b) {
  
    unsigned long long int x,y,sum;
    char *resend;
    resend = malloc(30);
    x = strtoull(a,NULL,10);
    y = strtoull(b,NULL,10);
    sum = x + y;
    sprintf(resend, "%llu", sum);
    return resend;
}
Il codice mi va a buon fine, supera tutti i test tranne ovviamente il seguente:
For inputs:
a = 63829983432984289347293874
b = 90938498237058927340892374089
Expected: 91002328220491911630239667963
Submitted: 18446744073709551614
Essendo 18446744073709551615 il più grande numero rappresentabile per un unsigned lond long int

Ho letto di un tipo denominato __int128 che potrebbe risolvermi il problema ma non riesco a capire come usarlo in quanto mi da sempre lo stesso risultato.

Come posso rappresentare questo numero così elevato?

Grazie mille

5 Risposte

  • Non devi operare con variabili numeriche ma lavorare con le stringhe, carattere per carattere.
  • Okok.. quindi devo fare proprio l'addizione cifra per cifra riportandomi l'eventuale riporto.. grazie mille!!!
  • Qualcosa del genere, fatta velocemente ...
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    char *add(const char *a, const char *b) 
    {
    	int i, j, v, cy;
    
    	int lSP = strlen(a);
    	int lSM = strlen(b);
    	const char *pSP = a;
    	const char *pSM = b;
    
    	if (lSM > lSP)
    	{
    		lSP = strlen(b);
    		lSM = strlen(a);
    		pSP = b;
    		pSM = a;
    	}
    
    	char *res = (char *)calloc(lSP + 1, sizeof(char));
    	strcpy(res, pSP);
    	
    	cy = 0;
    	j = lSP-1;
    	for (i = lSM-1; i >= 0; i--)
    	{
    		v = cy + res[j] - '0' + pSM[i] - '0';
    		cy = v / 10;
    		v %= 10;
    		res[j] = '0' + v;
    		j--;
    	}
    
    	while(j)
    	{
    		v = cy + res[j] - '0';
    		cy = v / 10;
    		v %= 10;
    		res[j] = '0' + v;
    		j--;
    	}
    
    	return res;
    }
    
    int main()
    {
    	char a[] =    "63829983432984289347293874";
    	char b[] = "90938498237058927340892374089";
    
    	printf("Somma %s\n", add(a,b));
    
        return 0;
    }
    
  • Troppo velocemente mi sa!

    Innanzitutto la condizione del while dovrebbe essere modificata in j>=0 altrimenti:
    - se i due addendi hanno la stessa lunghezza il programma crasha in quanto all'uscita del for j assume un valore negativo;
    - se i due addendi hanno lunghezza diversa, un eventuale riporto per la prima cifra del numero più lungo non verrà considerato.

    A quel punto il programma funziona a patto che la somma abbia lo stesso numero di cifre dell'addendo maggiore, infatti il problema logico di fondo del codice è proprio questo, ossia non prevedere un ulteriore carattere nell'allocazione della stringa res.

    In ogni caso io farei qualcosa del genere:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    void inverti_stringa(char *s)
    {
        unsigned int dim_s = strlen(s);
        for(unsigned int i = 0; i < dim_s / 2; ++i)
        {
            char temp = s[i];
            s[i] = s[dim_s - i - 1];
            s[dim_s - i - 1] = temp;
        }
    }
    
    char* add(const char *a, const char *b)
    {
        unsigned int i;
        unsigned int n = 0;
        unsigned int dim_a = strlen(a);
        unsigned int dim_b = strlen(b);
    	unsigned int dim_max = dim_a > dim_b ? dim_a : dim_b;
    	char *c = (char*)malloc((dim_max + 2) * sizeof(char));
    	for(i = 0; i < dim_max; ++i)
        {
            n /= 10;
            if(i < dim_a)
            {
                n += a[dim_a - i - 1] - '0';
            }
            if(i < dim_b)
            {
                n += b[dim_b - i - 1] - '0';
            }
            c[i] = n % 10 + '0';
        }
        if(n / 10)
        {
            c[i++] = '1';
        }
        c[i] = '\0';
        inverti_stringa(c);
    	return c;
    }
    
    int main()
    {
    	char a[] = "999";
    	char b[] = "21";
    	printf("%s+%s=%s\n", a, b, add(a, b));
        return 0;
    }
  • Certo il codice andava rivisto ... avevi detto che era fatto velocemente... ma tanto l'opposto non ha proprio risposto...

    P.S. Alla fine potevi scrivere _strrev(c);
Devi accedere o registrarti per scrivere nel forum
5 risposte