PROBLEMA Programma in C per trovare numeri di Armstrong

Pubblicità
L'ho appena provato e, madonna, è estremamente esoso di risorse, ram, processore, batteria... tutto. Ed è anche ostico di configurazione
 
@BAT @DispatchCode scusate ma mi è venuto un dubbio. Per evitare l'overflow (che da quanto ho capito è provocato dal fatto che il programma se analizza numero con più di tot cifre da errore) non si potrebbe analizzare una cifra per volta? Sempre con il metodo degli interi
 
@BAT @DispatchCode scusate ma mi è venuto un dubbio. Per evitare l'overflow (che da quanto ho capito è provocato dal fatto che il programma se analizza numero con più di tot cifre da errore) non si potrebbe analizzare una cifra per volta? Sempre con il metodo degli interi

Se usi un unsigned int spazi da 0 a oltre 4 miliardi. Non so quanti valori vuoi calcolare, ma è probabilmente un problema che puoi evitare di porti, dipende dai tuoi scopi.

Puoi anche usare come tipo long long, e avere quindi numeri a 64bit.

Il problema comunque è dovuto al fatto che ogni tipo ha ovviamente dei limiti. Ad esempio, 1byte sono 8bit e in 8 bit il numero massimo che puoi memorizzare è 2^8 (256 valori, da 0 a 255). Se è "signed" perdi un bit, che viene usato per il segno, quindi andrai da -128 a 127 (guardati il complemento a 2 se non lo conosci).
 
Ritornando al problema, avrei anche un'altra idea: detta f() la funzione che per ogni n restituisce la somma delle singole cifre elevate a potenza, è evidente che
f(12334)=f(43321)=f(32431)=...
ossia tra due potenze di 10 consecutive esistono una serie di numeri che sono fra loro "anagrammabili" e di cui risulta quindi superfluo calcolarne più volte la somma.
Con queste premesse il numero minimo di somme da calcolare (intese come chiamate ad
f()) dovrebbe essere dato dalle combinazioni con ripetizione C'(m,k) di m elementi (10 nel nostro caso, ossia le cifre 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) di classe k (pari nel nostro caso al numero di cifre considerato).

Essendo
C'(m,k)=(m+k-1)!/[k!(m-1)!]
nel nostro caso la formula si riduce a
C'(10,k)=(9+k)!/[k!(9)!]

Vediamo ora quante somme si "risparmiano" al variare del numero di cifre k; per farlo utilizzo la seguente formula:
C'(10,k)/[10^k-10^(k-1)]
che per un dato k calcola la percentuale di numeri da valutare su quelli totali (il denominatore infatti rappresenta il numero di tutti i possibili numeri a k cifre).

k%
261,111111111%
324,444444444%
47,944444444%
52,224444444%
60,556111111%
70,127111111%
80,027011111%
90,005402222%
100,001026422%
110,000186622%
120,000032659%
130,000005527%
140,000000908%
150,000000145%

Come si può vedere il "risparmio" teorico diventa al crescere di k sempre più consistente, bisogna però vedere se, al netto del suo costo computazionale, l'implementazione di questo approccio rappresenta un miglioramento o un peggioramento in termini di tempo d'esecuzione.
Dopo vedo di buttare giù qualche linea di codice...😕
C:
#include <stdio.h>
#include <inttypes.h>

#define K 18 //MAX 18

int combinazione_R_successiva(unsigned int *u, const unsigned int n, const unsigned int k)
{
    for(unsigned int i = k - 1; i < k; --i)
    {
        if(u[i] < n - 1)
        {
            if(++u[i] != n - 1)
            {
                for(unsigned int j = i + 1; j < k; u[j++] = u[i]);
            }
            return 1;
        }
    }
    return 0;
}

int is_armstrong(unsigned int *u, uint64_t *v, const unsigned int k, uint64_t *sum)
{
    unsigned int w[10] = {0};
    unsigned int i;
    for(i = 0; i < k; *sum += v[u[i]], ++w[u[i++]]);
    if(*sum >= v[10] / 10 && *sum < v[10])
    {
        for(uint64_t temp = *sum; temp && w[temp % 10]--; temp /= 10, --i);
    }
    return !i;
}

int main()
{
    uint64_t v[11] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    for(unsigned int cont = 0, k = 1; k <= K; ++k)
    {
        for(uint64_t i = 2; i < 11; v[i] *= i, ++i);
        unsigned int u[K] = {0};
        do
        {
            uint64_t sum = 0;
            if(is_armstrong(u, v, k, &sum))
            {
                printf(" %2u: %"PRIu64"\n", ++cont, sum);
            }
        }
        while(combinazione_R_successiva(u, 10, k));
    }
    return 0;
}

Sembra funzionare! 😀

Qui ho impostato K=9 in modo da confrontare il tempo d'esecuzione con quello dei precedenti codici:
Codice:
  1: 1
  2: 2
  3: 3
  4: 4
  5: 5
  6: 6
  7: 7
  8: 8
  9: 9
 10: 370
 11: 407
 12: 153
 13: 371
 14: 8208
 15: 1634
 16: 9474
 17: 93084
 18: 92727
 19: 54748
 20: 548834
 21: 9800817
 22: 4210818
 23: 1741725
 24: 9926315
 25: 24678050
 26: 24678051
 27: 88593477
 28: 146511208
 29: 912985153
 30: 472335975
 31: 534494836

Process returned 0 (0x0)   execution time : 0.054 s
Press any key to continue.

Qui invece ho impostato K=18 (massimo valore compatibile con gli interi a 64 bit; per andare oltre e spingersi fino a K=39 bisogna utilizzare una libreria per i big int, qualche tempo fa ne ho implementato una, poi nel caso ci provo):
Codice:
  1: 1
  2: 2
  3: 3
  4: 4
  5: 5
  6: 6
  7: 7
  8: 8
  9: 9
 10: 370
 11: 407
 12: 153
 13: 371
 14: 8208
 15: 1634
 16: 9474
 17: 93084
 18: 92727
 19: 54748
 20: 548834
 21: 9800817
 22: 4210818
 23: 1741725
 24: 9926315
 25: 24678050
 26: 24678051
 27: 88593477
 28: 146511208
 29: 912985153
 30: 472335975
 31: 534494836
 32: 4679307774
 33: 32164049650
 34: 40028394225
 35: 42678290603
 36: 49388550606
 37: 32164049651
 38: 94204591914
 39: 44708635679
 40: 82693916578
 41: 28116440335967
 42: 4338281769391370
 43: 4338281769391371
 44: 35875699062250035
 45: 21897142587612075
 46: 35641594208964132

Process returned 0 (0x0)   execution time : 0.715 s
Press any key to continue.

Magari dopo con calma spiego meglio l'algoritmo che ho adottato.
 
Per evitare l'overflow (che da quanto ho capito è provocato dal fatto che il programma se analizza numero con più di tot cifre da errore) non si potrebbe analizzare una cifra per volta? Sempre con il metodo degli interi
sei abituato con Python che usa i numeri interi a precisione limitata solo dalla macchina, quindi sulla carta, tempi di eleaborazioe a parte, con Python puoi maneggiare numeri di lunghezza a piacere.
Con linguaggi come C/C++, Java ecc. i tipi "primitivi" per questioni di efficienza non sono implementati come oggetti (come fa Python) ma hanno una dimensione prefissata in bit. Per esempio gli interi int negli attuali sistemi sono generalmente a 32 bit
dato che con N bit si possono rappresentare al massimo 2^N valori l'intervallo ove fare i calcoli è limitato; per esempio gli interi con segno a 32 bit vanno da -2^31 a 2^31-1 (cioè da -2.147.483.648 a +2.147.483.647, sono 2^32=4.294.967.296 numeri);
gli int (32 bit) o tipi più "grandi" (in bit) vanno bene per i problemi comuni.
I numeri interi però sono brutte bestie, i problemi che li coinvolgono sono semplicissimi da capire (mediamente alla portata di un bambino delle scuole medie inferiori) e sulla carta è semplice scrivere gli algoritmi che li risolverebbero, il problema è i programmini risolutivi spesso giocano brutti scherzi.

In C i range dei numeri sono contenuti in un header chiamato limits.h, è importante conoscere i limiti del linguaggio per cercare di evitare errori. Il formato dei numeri dipende dal compilatore usato (eventualmente dalla sua versione). Puoi usare questo programma per vedere i limiti del tuo compilatore sui tipi più comunemente usati

C:
#include <stdio.h>
#include <limits.h>

int main(void) {
    printf("--------------------------------------------------------------\n");
    printf("TIPI INTERI\n");
    printf("--------------------------------------------------------------\n");
    printf("Tipo               INTERVALLO\n");
    printf("--------------------------------------------------------------\n");
    printf("char               [%d, %d]\n", CHAR_MIN, CHAR_MAX);
    printf("unsigned char      [%u, %u]\n", '\0', UCHAR_MAX);
    printf("short              [%d, %d]\n", SHRT_MIN, SHRT_MAX);
    printf("unsigned short     [%u, %u]\n", 0, USHRT_MAX);
    printf("int                [%d, %d]\n", INT_MIN, INT_MAX);
    printf("unsigned           [%u, %u]\n", 0, UINT_MAX);
    printf("long               [%ld, %ld]\n", LONG_MIN, LONG_MAX);
    printf("unsigned long      [%lu, %lu]\n", 0, ULONG_MAX);
    printf("long long          [%lld, %lld]\n", LLONG_MIN, LLONG_MAX);
    printf("unsigned long long [%llu, %llu]\n", 0, ULLONG_MAX);
    printf("--------------------------------------------------------------\n");
    return 0;
}

questo invece è per i numeri in virgola mobile:

C:
#include <stdio.h>
#include <float.h> // header per limiti di numeri in virgola mobile

int main(void) {
    printf("-----------------------------------------------------\n");
    printf("TIPI IN VIRGOLA MOBILE\n");
    printf("-----------------------------------------------------\n");
    printf("Tipo        INTERVALLO               PRECISIONE\n");
    printf("-----------------------------------------------------\n");
    printf("float       [%.3e, %.3e]    %u cifre\n", FLT_MIN, FLT_MAX, FLT_DIG);
    printf("double      [%.3e, %.3e] %u cifre\n", DBL_MIN, DBL_MAX, DBL_DIG);
    printf("long double [%.3e, %.3e] %u cifre\n", LDBL_MIN, LDBL_MAX, LDBL_DIG);
    printf("-----------------------------------------------------\n");
    return 0;
}

Viceversa, con l'operatore sizeof puoi conoscere la dimensione in byte di un determinato tipo:

C:
#include <stdio.h>
#include<stdbool.h>

int main(void){
    printf("------------------------------------------\n");
    printf("OPERATORE sizeof(TIPO)\n");
    printf("------------------------------------------\n");
    printf("Tipo                  Byte\n");
    printf("------------------------------------------\n");
    printf("_Bool                 %2u\n", sizeof(_Bool));
    printf("bool                  %2u\n", sizeof(bool));
    printf("char                  %2u\n", sizeof(char));
    printf("unsigned char         %2u\n", sizeof(unsigned char));
    printf("short                 %2u\n", sizeof(short));
    printf("unsigned short        %2u\n", sizeof(unsigned short));
    printf("int                   %2u\n", sizeof(int));
    printf("unsigned              %2u\n", sizeof(unsigned));
    printf("long                  %2u\n", sizeof(long));
    printf("unsigned long         %2u\n", sizeof(unsigned long));
    printf("long long             %2u\n", sizeof(long long));
    printf("unsigned long long    %2u\n", sizeof(unsigned long long));
    printf("float                 %2u\n", sizeof(float));
    printf("double                %2u\n", sizeof(double));
    size_t byteLongDouble = sizeof(long double);
    printf("long double           %2u\n", byteLongDouble);
    printf("------------------------------------------\n");
    return 0;
}
 
Ultima modifica:
Sembra funzionare!
👍 quello che hai appena brillantemente risolto è un "crivello" (se mi passi il termine) di numeri di Armstrong, ossia un modo per generarli
sicuramente molto più efficiente rispetto al test su singolo numero e ciclo for su intervallo, meriti il mio applauso a scena aperta 👏
 
sei abituato con Python che usa i numeri interi a precisione limitata solo dalla macchina, quindi sulla carta, tempi di eleaborazioe a parte, con Python puoi maneggiare numeri di lunghezza a piacere.
Con linguaggi come C/C++, Java ecc. i tipi "primitivi" per questioni di efficienza non sono implementati come oggetti (come fa Python) ma hanno una dimensione prefissata in bit. Per esempio gli interi int negli attuali sistemi sono generalmente a 32 bit
dato che con N bit si possono rappresentare al massimo 2^N valori l'intervallo ove fare i calcoli è limitato; per esempio gli interi con segno a 32 bit vanno da -2^31 a 2^31-1 (cioè da -2.147.483.648 a +2.147.483.647, sono 2^32=4.294.967.296 numeri);
gli int (32 bit) o tipi più "grandi" (in bit) vanno bene per i problemi comuni.
I numeri interi però sono brutte bestie, i problemi che li coinvolgono sono semplicissimi da capire (mediamente alla portata di un bambino delle scuole medie inferiori) e sulla carta è semplice scrivere gli algoritmi che li risolverebbero, il problema è i programmini risolutivi spesso giocano brutti scherzi.

In C i range dei numeri sono contenuti in un header chiamato limits.h, è importante conoscere i limiti del linguaggio per cercare di evitare errori. Il formato dei numeri dipende dal compilatore usato (eventualmente dalla sua versione). Puoi usare questo programma per vedere i limiti del tuo compilatore sui tipi più comunemente usati

C:
#include <stdio.h>
#include <limits.h>

int main(void) {
    printf("--------------------------------------------------------------\n");
    printf("TIPI INTERI\n");
    printf("--------------------------------------------------------------\n");
    printf("Tipo               INTERVALLO\n");
    printf("--------------------------------------------------------------\n");
    printf("char               [%d, %d]\n", CHAR_MIN, CHAR_MAX);
    printf("unsigned char      [%u, %u]\n", '\0', UCHAR_MAX);
    printf("short              [%d, %d]\n", SHRT_MIN, SHRT_MAX);
    printf("unsigned short     [%u, %u]\n", 0, USHRT_MAX);
    printf("int                [%d, %d]\n", INT_MIN, INT_MAX);
    printf("unsigned           [%u, %u]\n", 0, UINT_MAX);
    printf("long               [%ld, %ld]\n", LONG_MIN, LONG_MAX);
    printf("unsigned long      [%lu, %lu]\n", 0, ULONG_MAX);
    printf("long long          [%lld, %lld]\n", LLONG_MIN, LLONG_MAX);
    printf("unsigned long long [%llu, %llu]\n", 0, ULLONG_MAX);
    printf("--------------------------------------------------------------\n");
    return 0;
}

questo invece è per i numeri in virgola mobile:

C:
#include <stdio.h>
#include <float.h> // header per limiti di numeri in virgola mobile

int main(void) {
    printf("-----------------------------------------------------\n");
    printf("TIPI IN VIRGOLA MOBILE\n");
    printf("-----------------------------------------------------\n");
    printf("Tipo        INTERVALLO               PRECISIONE\n");
    printf("-----------------------------------------------------\n");
    printf("float       [%.3e, %.3e]    %u cifre\n", FLT_MIN, FLT_MAX, FLT_DIG);
    printf("double      [%.3e, %.3e] %u cifre\n", DBL_MIN, DBL_MAX, DBL_DIG);
    printf("long double [%.3e, %.3e] %u cifre\n", LDBL_MIN, LDBL_MAX, LDBL_DIG);
    printf("-----------------------------------------------------\n");
    return 0;
}

Viceversa, con l'operatore sizeof puoi conoscere la dimensione in byte di un determinato tipo:

C:
#include <stdio.h>
#include<stdbool.h>

int main(void){
    printf("------------------------------------------\n");
    printf("OPERATORE sizeof(TIPO)\n");
    printf("------------------------------------------\n");
    printf("Tipo                  Byte\n");
    printf("------------------------------------------\n");
    printf("_Bool                 %2u\n", sizeof(_Bool));
    printf("bool                  %2u\n", sizeof(bool));
    printf("char                  %2u\n", sizeof(char));
    printf("unsigned char         %2u\n", sizeof(unsigned char));
    printf("short                 %2u\n", sizeof(short));
    printf("unsigned short        %2u\n", sizeof(unsigned short));
    printf("int                   %2u\n", sizeof(int));
    printf("unsigned              %2u\n", sizeof(unsigned));
    printf("long                  %2u\n", sizeof(long));
    printf("unsigned long         %2u\n", sizeof(unsigned long));
    printf("long long             %2u\n", sizeof(long long));
    printf("unsigned long long    %2u\n", sizeof(unsigned long long));
    printf("float                 %2u\n", sizeof(float));
    printf("double                %2u\n", sizeof(double));
    size_t byteLongDouble = sizeof(long double);
    printf("long double           %2u\n", byteLongDouble);
    printf("------------------------------------------\n");
    return 0;
}
Si, conosco il limite di memoria legato ai tipi di int nel C, ma mettendo un long long int come variabile per il numero da analizzare corrente, e analizzando una cifra alla volta con un'altra variabile, non si ovvia il problema dell'overflow? 1,8x10^8 sono tante cifre, direi che bastano.
Che poi, se python è programmato in C, come fa a accettare numeri più grandi di 8 byte?
 
mettendo un long long int come variabile per il numero da analizzare corrente, e analizzando una cifra alla volta con un'altra variabile, non si ovvia il problema dell'overflow?
no: il singolo numero da analizzare devi lasciarlo come int a 32 bit (il parametro della funzione deve rimanere int), invece la variabile per la somma e le potenze che calcoli devono essere long long, in modo da evitare calcoli errati

Che poi, se python è programmato in C, come fa a accettare numeri più grandi di 8 byte?
non c'entra nulla: anche la Java Virtual Machine è programmata in C e Java ha delle classi per l'aritmetica a precisione arbitraria
 
Ultima modifica:
@M1n021 complimenti, mi accodo a BAT. Codici tutt'altro che banali, fanno anche capire che non hai solo basi solide di programmazione.
Una curiosità, fai il programmatore per lavoro o è solo una passione e ti occupi di altro (o magari studi ancora)?

Ho provato il tuo codice (k=18), sul fisso (i9 10900kf) ottengo questi tempi:

Codice:
real    0m0.847s
user    0m0.000s
sys     0m0.000s

Compilando con O3
Codice:
real    0m0.408s
user    0m0.000s
sys     0m0.000s

Anche in questo caso ho visto che viene fatto uso del set SSE.
 
Magari dopo con calma spiego meglio l'algoritmo che ho adottato.
Dal momento che mi rendo conto di aver scritto del codice forse un po' ostico per chi è ancora alle prime armi, cerco di abbozzare un minimo di spiegazione.

Per simulare le sequenze relative alle combinazioni con ripetizione ho implementato la funzione combinazione_R_successiva(), la quale, partendo dalla sequenza attuale (contenuta nei primi k elementi di u), ritorna true se è stato possibile aggiornare u alla sequenza successiva oppure false se la sequenza corrente è quella finale (costituita da tutti 9). Per chiarire meglio quello che intendo, riporto come esempio parte dell'elenco delle 220 combinazioni con ripetizione per n=10 e k=3:
Codice:
   1: 0 0 0
   2: 0 0 1
   3: 0 0 2
   4: 0 0 3
   5: 0 0 4
   6: 0 0 5
   7: 0 0 6
   8: 0 0 7
   9: 0 0 8
  10: 0 0 9
  11: 0 1 1
  12: 0 1 2
  13: 0 1 3
  14: 0 1 4
  15: 0 1 5
  16: 0 1 6
  17: 0 1 7
  18: 0 1 8
  19: 0 1 9
  20: 0 2 2
       ...
  52: 0 7 9
  53: 0 8 8
  54: 0 8 9
  55: 0 9 9
  56: 1 1 1
  57: 1 1 2
  58: 1 1 3
  59: 1 1 4
  60: 1 1 5
  61: 1 1 6
  62: 1 1 7
  63: 1 1 8
  64: 1 1 9
  65: 1 2 2
       ...
 206: 6 7 8
 207: 6 7 9
 208: 6 8 8
 209: 6 8 9
 210: 6 9 9
 211: 7 7 7
 212: 7 7 8
 213: 7 7 9
 214: 7 8 8
 215: 7 8 9
 216: 7 9 9
 217: 8 8 8
 218: 8 8 9
 219: 8 9 9
 220: 9 9 9

L'array v, che viene aggiornato ad ogni modifica di k, contiene elementi il cui valore è uguale al corrispettivo indice elevato al numero k di cifre considerate.

Presa una generica sequenza contenuta in u, diventa quindi immediato calcolare la somma ad essa relativa. Per esempio considerando la sequenza (1 3 5), la somma può essere calcolata semplicemente come
sum=v[1]+v[3]+v[5]=153
essendo
v[1]=1^3
v[3]=3^3
v[5]=5^3


A questo punto non resta che verificare se sum=153 è un numero di Armstrong o meno, e per farlo è sufficiente verificare due semplici condizioni:
1) l'intero sum deve avere un numero di cifre uguale al valore corrente di k (pari a 3 nell'esempio considerato). Ciò può essere fatto semplicemente ricorrendo a v[10] mediante la condizione v[10]/10<=sum<v[10] (che nel caso specifico, essendo v[10]=10^3=1000, si traduce in 100<=153<1000);
2) le k cifre che costituiscono sum devono essere le stesse (anche se in ordine sparso) che costituiscono la sequenza in u. Ciò nel codice lo faccio appoggiandomi ad un array w che funge da una sorta di tabella hash.



@BAT & @DispatchCode
grazie davvero per le belle parole! 😊

Una curiosità, fai il programmatore per lavoro o è solo una passione e ti occupi di altro (o magari studi ancora)?
Diciamo che più o meno studio ancora, in ogni caso non sono un programmatore né studio informatica, mi sono avvicinato alla programmazione grazie ad un esame a scelta di fondamenti da 6 crediti durante la triennale; da lì mi sono appassionato alla materia e ho approfondito un po' di C e C++ da autodidatta.
Alla fine si tratta di un hobby ed utilizzo la programmazione fondamentalmente come esercizio di logica... mi diverto a risolvere problemi e ad inventare algoritmi partendo da zero! 😁
 
Ho voluto provare anch'io a entrare nella corsa all'ottimizzazione. So che sicuramente non sarà ottimizzato come i vostri, ma dovrei aver ridotto i tempi di esecuzione rispetto al primo codice postato. L'unica cosa: compila ma non manda nessun output, ma non mi da errori.

C:
#include <stdio.h>

int myPow(int base, int exponent) {
    for(int i = 0; i < exponent; i++) {
        base *= base;
    }

    return base;
}

int isArmstrong(long long int num) {
    int digit, powered_digit, num2 = num, num3 = num, exponent = 0, check_num = 0;

    if(num > 10) return 1;

    while(num2 != 0) {
        num2 % 10;
        exponent++;
    }

    while(num != 0) {
        digit = num % 10;
        powered_digit = myPow(digit, exponent);

        check_num +=  powered_digit;    
    }  

    if(check_num = num3) return 1;
    else return 0;
}

int main(int argc, char const *argv[]) {
    for(long long int i = 0; i < 2000000; i++) {
        if(isArmstrong(i)) printf("%lld\n", i);
    }

    return 0;
}
 
L'unica cosa: compila ma non manda nessun output, ma non mi da errori.
Partiamo dalla funzione myPow():
- se stai utilizzando i long long int allora la funzione deve tornare un long long int;
- ipotizzando base=2 e exponent=3, al momento la funzione effettua il seguente calcolo:
base=2*2=4
base=4*4=16
base=16*16=256

che evidentemente non è il risultato di 2^3 che è uguale a 8.
Un modo per risolvere è quello di usare un'ulteriore variabile di tipo long long int (chiamiamola a) inizializzata ad 1, in cui salvare il risultato dell'elevamento a potenza. In questo modo, impostando a*=base, si ha:
a=1*2=2
a=2*2=4
a=4*2=8


Passiamo ora alla funzione isArmstrong():
- se utilizzi il tipo long long int, allora almeno le variabili powered_digit, num2, num3 e check_sum devono essere long long int;
- if(num>10)return1 dovrebbe essere in realtà if(num<10)return1, in ogni caso io lo toglierei proprio e lascerei verificare al programma che i numeri <10 sono numeri di Armstrong;
- questo
C:
while(num2 != 0)
{
    num2 % 10;
    exponent++;
}
è un ciclo infinito, in quanto num2 non viene mai modificato. In ogni caso se lo scopo è quello di calcolare il numero di cifre di num devi modificarlo in questo modo:
C:
while(num2 != 0)
{
    num2 /= 10;
    exponent++;
}
- EDIT: stessa cosa per il secondo while, devi aggiungere num /= 10;
- la seguente parte di codice
C:
if(check_num = num3) return 1;
else return 0;
può essere semplificata in
C:
return check_num == num3;
[EDIT da notare che sopra utilizzavi = al posto di ==]

Infine per quanto riguarda il main(), mi sembra di capire che lo specificatore %lld non funziona sotto windows utilizzando mingw, in tal caso bisogna utilizzare lo specificatore %I64d.
In ogni caso per rendere il codice più portabile ti consiglio di includere l'header inttypes.h e di sostituire i long long int con il tipo int64_t (che richiede lo specificatore, sempre valido, PRId64).
 
Ultima modifica:
Grazie per l'analisi. La maggior parte degli errori sono soprattutto causati dalla distrazione e dal fatto che il debug in vsc e gcc non funziona (vai a sapere perché), se no li avrei risolti in un attimo.

Infine per quanto riguarda il main(), mi sembra di capire che lo specificatore %lld non funziona sotto windows utilizzando mingw, in tal caso bisogna utilizzare lo specificatore %I64d.
In ogni caso per rendere il codice più portabile ti consiglio di includere l'header inttypes.h e di sostituire i long long int con il tipo int64_t (che richiede lo specificatore, sempre valido, PRIu64).
Qui non ho la minima idea di cosa tu abbia scritto, ma mi documenterò. Intanto correggo gli errori precedenti

- se stai utilizzando i long long int allora la funzione deve tornare un long long int;
Però la funzione deve elevare a potenza solo una cifra, andando quindi a lavorare su un tipo int semplice. Non capisco perché riservare più memoria del necessario quando me la sbrigo con un int

C:
return check_num = num3;
Credo tu abbia sbagliato a scrivere, ma non dovrebbe essere return check_num == num3?



EDIT: ho provato a eseguire il codice corretto, ma mi stampa fino a 9
 
Ultima modifica:
EDIT: ho provato a eseguire il codice corretto, ma mi stampa fino a 9
Postalo, così possiamo darci un'occhiata.
Comunque avevo aggiunto delle modifiche al mio precedente post, non so se ci hai fatto caso.


Però la funzione deve elevare a potenza solo una cifra, andando quindi a lavorare su un tipo int semplice. Non capisco perché riservare più memoria del necessario quando me la sbrigo con un int
9^10=3.486.784.401 > 2.147.483.647=max_value(int)
 
Pubblicità
Pubblicità

Discussioni Simili

Indietro
Top