PROBLEMA Programma in C per trovare numeri di Armstrong

BAT

Moderatore
Staff Forum
Utente Èlite
23,074
11,653
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
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
 

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
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
Post unito automaticamente:

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:

M1n021

Utente Attivo
159
73
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);
 

BAT

Moderatore
Staff Forum
Utente Èlite
23,074
11,653
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
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?
 

Andretti60

Utente Èlite
6,440
5,091
…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.
 

BAT

Moderatore
Staff Forum
Utente Èlite
23,074
11,653
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
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
 

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
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
 
  • Haha
Reazioni: BAT

BAT

Moderatore
Staff Forum
Utente Èlite
23,074
11,653
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
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
 

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
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?
 
  • Wow
Reazioni: BAT

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,233
1,865
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
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... 😉
 

Ibernato

Utente Èlite
4,333
2,048
OS
Windows 10 Pro / Ubuntu 22.04
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.
 

Hero467

Utente Attivo
689
404
OS
I use ARCH btw
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
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili