PROBLEMA Programma in C per trovare numeri di Armstrong

Pubblicità
Non capisco perché riservare più memoria del necessario quando me la sbrigo con un int
te l'ho detto almeno 3 volte, 9^10 dentro 32 bit non ci va ed è solo un esempio, anche 8^10 fa più di un miliardo, il che significa che qualunque numero di 10 cifre che abbia 4-5 cifre 8 fa sbagliare i calcoli
la tua funzione dovrebbe operare su input int ma fare i calcoli interni su long long
 
te l'ho detto almeno 3 volte, 9^10 dentro 32 bit non ci va ed è solo un esempio, anche 8^10 fa più di un miliardo, il che significa che qualune numero di 10 cifre che abbia 4-5 cifre 8 fa sbagliare i calcoli
la tua funzione dovrebbe operare su input int ma fare i calcoli interni su long long
ah, ops. Non me ne ero accorto. Correggo subito
--- i due messaggi sono stati uniti ---
Postalo, così possiamo darci un'occhiata.
Comunque avevo aggiunto delle modifiche al mio precedente post, non so se ci hai fatto caso.
Le ho notate adesso, sistemo

Codice:
C:
#include <stdio.h>
#include <inttypes.h>

int64_t myPow(int base, int exponent) {
    int64_t base2 = base;

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

    return base;
}

int64_t isArmstrong(int64_t num) {
    int64_t 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;     
    }   

    return check_num == num3;
}

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

    return 0;
}
Non mi accetta %l64d come specificatore, quindi mi manda a schermo quello. Con %lld mi manda a schermo i numeri da 0 a 9, poi 4150 e 4151, e si ferma. Salta numeri come il 153, il 370...
 
Ultima modifica:
Come detto nell'altro post:
- anche nel secondo while bisogna aggiungere num/=10;
- la funzione myPow() deve ritornare e lavorare sulla variabile base2, che inoltre va inizializzata ad 1;
- il modo corretto di scrivere quella printf() nel main() è:
C:
printf("%" PRId64 "\n", i);
- infine nella funzione
isArmstrong() puoi tranquillamente fare a meno delle variabili digit e powered_digit scrivendo:
C:
check_num += myPow(num % 10, exponent);
 
Non ho capito, puoi spiegarmi meglio?
la variabile che memorizza il prodotto deve essere inizializzata a 1 (come inizializzi a zero quella della somma)
il corpo della funzione è sbagliato, chiama il prodotto da restituire semplicemente p e poni p=1, tu l'hai chiamato base2 ma poi ritroni base: che PESSIMA ABITUDINE quella di non metere i commenti! Vengono rimossi dal compilatore, io quando programmo scrivo più commenti che codice

mi sembra che nel corpo della potenza hai fatto confusione proprio perché non metti in un commento cosa dovrebbe fare la variabile e soprattutto non dai nomi significativi: se devi ritornare una potenza chiama la vcariabile "potenza" oppure p mettendoci un commento:
int64_t p = 1; // potenza da restituire, è tanto difficile?
 
…che PESSIMA ABITUDINE quella di non metere i commenti! …
Un codice scritto bene NON richiede nessun commento. Come dice Robert Martin (l’autore di Clean Code) sono veramente pochissimi i casi in cui i commenti siano “accettabili” (neanche “necessari”); un codice scritto bene si auto commenta da solo.
 
Un codice scritto bene NON richiede nessun commento
il nostro amico sta imparando a programmare, come mantra ci martellavano "date nomi significativi alle variabili, mettete dei commenti"
poi ognuno è libero di chiamare "Geremia" una variabile che dovrebbe contenere l'area di un trapezio e senza scrivere un commento a fianco. Ma io continuerò a non suggerirlo
 
No, la funzione ritorna esattamente quello che ho pensato debba ritornare: base è il numero da elevare a potenza, e siccome se lo moltiplicavo per se stesso continuamente faceva 2x2, 4x4, 8x8... come ha fatto notare @M1n021, allora ho creato base2, che acquista il valore iniziale di base e resta immutato, cos^ base viene moltiplicato continuamente per il suo valore originale tante volte quante l'esponente vale

Però è vero, metto pochi commenti, ho questa brutta abitudine, visto che programmo da solo e mi ricordo cosa fa quello che scrivo


Ps: mi piace geremia come nome per una variabile
 
la funzione ritorna esattamente quello che ho pensato debba ritornare
non mi sembra proprio, se il codice è rimasto quello di prima e non lo hai corretto il calcolo è sbagliato, fa una moltiplicazione di troppo, l'inizializzazione è errata;
se calcolo mentalmente 3^1 seguendo quelle istruzioni di myPow ecco cosa esce fuori
passi myPow(3,1) dovrebbe restiuire 3, invece
base=3, exponent=1
dopo la prima istruzione base2=3
quindi il ciclo viene eseguito una volta e fa una moltiplicazione 3*3 e alla fine ritorna 9, provaci se non ci credi

devi inizializzare base2=1 (è quella che io ho chiamato p nel mio commento precedente, e nel ciclo base2 *= base
e il return deve essere return base2
 
Ho riscritto il programma in Java, per confrontare i tempi di esecuzione, e stranamente Java è molto più veloce di quello in C. Ho copiato passo passo le istruzioni, cambiando i dati dove serviva, ma la struttura in se è identica. Come mai questa cosa?
 
Ho riscritto il programma in Java, per confrontare i tempi di esecuzione, e stranamente Java è molto più veloce di quello in C. Ho copiato passo passo le istruzioni, cambiando i dati dove serviva, ma la struttura in se è identica. Come mai questa cosa?
Pubblica anche quello, così vediamo come l'hai scritto. Anzi, pubblicali entrambi.

@M1n021 ci avrei scommesso, davo per scontato non lavorassi come programmatore... 😉
 
Ho riscritto il programma in Java, per confrontare i tempi di esecuzione, e stranamente Java è molto più veloce di quello in C. Ho copiato passo passo le istruzioni, cambiando i dati dove serviva, ma la struttura in se è identica. Come mai questa cosa?
Ho riso appena ho letto questo post.
Mi sembra strano che Java sai più veloce di C.
 
Pubblica anche quello, così vediamo come l'hai scritto. Anzi, pubblicali entrambi.
Java:
public class Main {

    public static long pow(long base, int exponent) {
        long base2 = 1;

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

        return base2;
    }

    public static boolean isArmstrong(long num) {
        long num2 = num, num3 = num, check_num = 0;
        int exponent = 0;

        if (num < 10) return true;

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

        while (num != 0) {
            check_num += pow(num % 10, exponent);

            num /= 10;
        }

        return check_num == num3;
    }

    public static void main(String[] args) {
        for (long i = 0; i < pow(2, 25); i++) {
            if (isArmstrong(i)) System.out.println(i);
        }
    }
}


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

int64_t myPow(int base, int exponent) {
    int64_t base2 = 1;

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

    return base2;
}

int64_t isArmstrong(int64_t num) {
    int64_t num2 = num, num3 = num, exponent = 0, check_num = 0;

    if(num < 10) return 1;

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

    while(num != 0) {
        check_num += myPow(num % 10, exponent);

        num /= 10;   
    }   

    return check_num == num3;
}

int main(int argc, char const *argv[]) {
    for(int64_t i = 0; i < myPow(2, 25); i++) {
        if(isArmstrong(i)) printf("%" PRId64 "\n", i);
    }

    return 0;
}

Output programma Java:
Codice:
0
1
2
3
4
5
6
7
8
9
153
370
371
407
1634
8208
9474
54748
92727
93084
548834
1741725
4210818
9800817
9926315
24678050
24678051

real    0m1,435s
user    0m1,372s
sys    0m0,020s

Output programma C:
Codice:
0
1
2
3
4
5
6
7
8
9
153
370
371
407
1634
8208
9474
54748
92727
93084
548834
1741725
4210818
9800817
9926315
24678050
24678051

real    0m5,460s
user    0m5,455s
sys     0m0,004s

Entrambi impostati per analizzare numeri fino a 2^25.


Ho riso appena ho letto questo post.
Mi sembra strano che Java sai più veloce di C.
Fa stranissimo anche a me, ma a quanto pare il java è quasi 5 volte più veloce
 
Pubblicità
Pubblicità

Discussioni Simili

Indietro
Top