[HOME - BASE Cinque - Appunti di Matematica ricreativa]

Numeri invarianti perfetti

Chi ha paura delle enormi creature
che si trovano un po' al di là dei comuni territori numerici?

Ringrazio Enrico Delfini per questo intervento al Forum.

Numeri invarianti perfetti (o piucheperfetti) sono detti i numeri di n cifre uguali alla somma delle n-esime potenze delle singole cifre da cui sono composti.

Esempio:
153 = 1^3 + 5^3 + 3^3
Il classico 153 è formato da 3 cifre ed è uguale alla somma dei cubi delle sua cifre.
Esistono altri tre invarianti perfetti di tre cifre.

1634 ; 8208 e un altro che non vi dico sono quelli di 4 cifre.

Chi vuole fare qualche esperimento in javascript può andare a La pagina aperta del 153 di questo sito.

Esiste almeno un invariante perfetto di 5, di 6, di 7, di 8 cifre.

Non ne conosco di 9, ma
4 679 307 774
è l'unico invariante perfetto di 10 cifre, cioè, ripeto, pari alla somma delle decime potenze delle sue dieci cifre.

E ora,....tenetevi forte:
115 132 219 018 763 992 565 095 597 973 971 522 401
è uguale alla somma delle 39-esime potenze delle sue 39 cifre!!!!

Leggo (sul già citato libro dell'ing. Cresci) che è stata dimostrata l'impossibilità di numeri invarianti perfetti di oltre 60 cifre, ma per ora il record è il mostro di 39.

Una particolarità: nel "mostro" vi è una presenza "anomala" di cifre dispari (28 a 11); secondo voi è un caso o c'è una ragione?


Risposte & riflessioni

Gianfranco Bo
In fondo faccio una proposta, qui tengo degli appunti di lavoro.

Esponente Algoritmo Tempo Numeri invarianti perfetti
2 ingenuo 0.11 nessun risultato
3 ingenuo 0.38 153
370
371
407
4 ingenuo 3.63 1634
8208
9474
5 ingenuo 44 54748
92727
93084
6 ingenuo 521 548834
7 ingenuo 6349 1741725
4210818
9800817
9926315
8 elab.x100 640 24678050
24678051
88593477
9 elab.x100 6503 146511208
472335975
534494836
10 Pasquale   4679307774
11 Pasquale   32164049650
32164049651
40028394225
42678290603
44708635679
49388550606
82693916578

12

     
13      
14 Pasquale   28116440335967
15      
16 Pasquale   4338281769391370
4338281769391371
17 Pasquale   35641594208964132
18      
19 Pasquale   1517841543307505039
3289582984443187032
20 Pasquale   63105425988599693916
21 Pasquale   128468643043731391252
22      
23 Pasquale   27879694893054074471405
24 Pasquale   174088005938065293023722
25 Pasquale   1553242162893771850669378
4422095118095899619457938
26      
27      
28      
29      
30      
31      
...      

39

Enrico Delfini  

115.132.219.018.763.992.565.095.597.973.971.522 400
115 132 219 018 763 992 565 095 597 973 971 522 401

40

     

Giorgio Dendi
Non so davvero come si faccia a trovare questi numeri senza un calcolatore. Ho visto che nessuno ha risposto alla domanda di Enrico sui numeri perfetti di tre cifre, e su quella mi sono cimentato. Ho fatto un'osservazione: ho scoperto che se c'è un numero perfetto con una certa caratteristica, allora si può scrivere subito un altro numero perfetto. Altre regole non ho trovato, e ho dovuto lavorare molto di penna e, dopo essermi scritto una tabellina, ho fatto molti calcoli. Ho trovato, oltre al 153, anche 370 e 407 e un altro, che, come dicevo sopra, si può trovare senza fare calcoli, ma con il semplice ragionamento a cui accennavo. Pensavo che Enrico non abbia citato l'ultimo numero perfetto di 4 cifre per lo stesso motivo per cui non cito io l'ultimo di 3 cifre: con una semplice osservazione si può ricavare, una volta che si sanno gli altri numeri perfetti? Io non ho trovato nulla.
Sarei curioso se qualcuno ha trovato qualche sistema per snellire la ricerca, se questa è fatta a mano, senza calcolatore. Ad esempio, pensavo di fare considerazioni su quante cifre pari e quante dispari c'erano, ma non mi ha aiutato molto. A questo punto non mi cimento di sicuro a cercare i numeri perfetti di 4 cifre.

Ecco la mia osservazione: se riesco a trovare un numero che sia uguale alla potenza n-esima delle sue cifre, nel caso che la sua ultima cifra sia 0, allora posso trovarne un altro con le stesse cifre, ma con in fondo 1 al posto di 0. Quindi avevo visto che 153, 370 e 407 sono tali che abc=a^3+b^3+c^3. Con l'osservazione appena fatta, posso dire che anche 371 godrà della stessa proprietà. Senza fare calcoli, ma avendo fiducia che qualcuno ha verificato la proprietà per il 370.

Utervis
Da questa si deduce anche che se l'ultima cifra è unitaria, come nel caso del 371, allora anche quello precedente deve essere un numero perfetto avendo accettato che il primo è stato già verificato! :-)))

Ma nel caso dei numeri a 4 cifre nessuno termina con zero od uno! :-(

Grazie a tale proprietà possiamo stabilire che anche:

115.132.219.018.763.992.565.095.597.973.971.522 400

deve essere un "mostro alla Enrico" nel senso che è un invariante perfetto uguale alla somma delle 39-esime potenze delle sue 39 cifre!

Tu che sai tutto sui numeri eri a conoscenza anche di tale guinnes?

Gianfranco Bo
Il MOSTRO di Delfini e la domanda di Peppe mi hanno notevolmente interessato e stimolato.
Perciò vorrei fare una proposta che è certamente nelle nostre capacità.

Possiamo trovare con il computer i numeri INVARIANTI PERFETTI fino all'esponente 60 ed oltre?
Possiamo poi chiederci: ci fidiamo del risultato? e se non ci fidiamo, come possiamo verificarlo?

VI RICORDO CHE:
Numeri invarianti perfetti (o piucheperfetti) sono detti i numeri di n cifre uguali alla somma delle n-esime potenze delle singole cifre da cui sono composti.
Esempio:
153 = 1^3 + 5^3 + 3^3
Il classico 153 è formato da 3 cifre ed è uguale alla somma dei cubi delle sua cifre.

Qualcuno ha detto che il computer è un cretino immensamente veloce.
L'uomo lo programma, creando degli algoritmi, e può sfruttare la sua velocità per ottenere risultati straordinari.
Però se anche gli algoritmi sono cretini, la velocità del computer è del tutto inutile. In certi casi avere un Commodore 64 (1 Mhz) o un Pentium x (1 Ghz) è praticamente la stessa cosa: il primo si siede al livello 6 e l'altro al livello 9. Mentre magari c'è bisogno di arrivare al livello 100.

Dunque l'equazione giusta è: genio lento + cretino veloce = buona matematica al computer

Da parte mia ho fatto un po' di ricerche in Internet e ho trovato un programma molto interessante:
è un interprete BASIC (implementato da un giapponese) che ha dell'incredibile.
Tra l'altro !!!!!LAVORA CON NUMERI razionali FINO A 10000 (dico diecimila) CIFRE!!!!!

Se vi interessa, lo potete scaricare a questo indirizzo.
ATTENZIONE: la prudenza non è mai troppa, NON sono in grado di verificare se contiene uno spyware, perciò l'ho caricato su un computer dove tengo del software in quarantena.

Copyright
SHIRAISHI Kazuo
e-mail kazuo.shiraishi@nifty.ne.jp
Web http://www.vector.co.jp/authors/VA008683/english


Qui sotto c'è il programma più ingenuo (per non dire cretino) del mondo che trova tutti i numeri invarianti perfetti.
L'unico input da dare è l'esponente, scrivendolo direttamente nel programma.

Il problema è che già per l'esponente = 7 il programma comincia a "sedersi", i tempi di attesa diventano lunghissimi.

Ecco una tabella degli esponenti e dei rispettivi tempi di calcolo.

esp - tempo (secondi)
2 - 0.11
3 - 0.38
4 - 3.63
5 - 44.27
6 - 520.53
7 - 6349

Ciò è dovuto all'ingenuità dell'algoritmo, che procede esaminando TUTTI i numeri dell'intervallo, e sommando le potenze ennesime di tutte le loro cifre.

Ad es. per n=7, esamina tutti i numeri da 1 000 000 a 9 999 999.

Immaginiamoci un po' quanti calcoli deve fare per n=39 o n=60.

Ho due domande da porre:

1) Come aumenta il tempo di calcolo in funzione di n, con questo algoritmo?

2) E' possibile migliorare drasticamente l'algoritmo in modo da rendere i tempi accettabili?

NOTA1: per migliorare l'algoritmo non c'è bisogno di conoscere né il BASIC né nessun altro linguaggio di programmazione.
NOTA2: a volte per migliorare un algoritmo bisogna farne uno completamente diverso
NOTA3: se conoscete un altro software specialista in grandi numeri, fatecelo sapere.

Ecco il programma

--------------------
DIM cifra(60)

LET t1 = TIME

PRINT "Inizio"

LET esponente = 7
LET inizio = 10^(esponente-1)
LET fine = 10^esponente-1

FOR i = inizio TO fine
LET somma=0
FOR j = 1 TO esponente
LET cifra(j) = VAL(mid$(STR$(i),j,1))
LET somma = somma+cifra(j)^esponente
NEXT j
IF somma = i THEN PRINT i
NEXT i

PRINT "Fine"

LET t2 = TIME
PRINT (t2-t1)

END
--------------------

Ecco i risultati con n = 2..7

n=2
nessun risultato

n=3
153
370
371
407

n=4
1634
8208
9474

n=5
54748
92727
93084

n=6
548834

n=7
1741725
4210818
9800817
9926315

Ringrazio Giovanni Macchia per il programma in C++
Giovanni Macchia
I tempi sono bassi (un programmino in C++ l'ho scritto io ed è ovviamente veloce) ma per n alto ci sono problemi di grandezza massima (anche se il programma l'ho scritto in 5 minuti e non ci ho perso molto la testa).

Ecco il programma; chiaramente, date le limitazioni dell'intero in C , per n maggiore di 10 dà problemi. Per il resto impiega pochi secondi. Devo risolvere il problema sostituendo ad int un double...
Non è granchè, ma per averlo scritto all'una di notte e in cinque minuti, va bene,,

#include <iostream>
#include <sstream>
#include <cstdlib>
using namespace std;

int power(long m, long n)
{
int k=1;
for (int i = 1;i<=n;i++)
k=k*m;
return(k);
}

void main ( )
{int esponente;
long j,m;char *p=new char;
int i, somma;
char *s=new char[80];
p[1]='\0';
cin >> esponente;
int min=power(10,(esponente - 1));
int max= power(10,esponente)-1;
i=min;
while(i<=max)
{
somma =0;
sprintf(s,"%d",i);
for (j=1;j<=esponente;j++)
{
p[0]=s[j-1];
sscanf(p,"%d",&m);
somma = somma + power(m,esponente);
}
if ((somma - i)==0) cout << i<<'\n';
i++;
}
cout << '\n'<< "Fine";
}

Ringrazio Pasquale per il meticoloso lavoro che ha fatto con il Decimal Basic. Copio qui sotto il suo programma e le istruzioni per utilizzarlo.
Pasquale
Come funziona:

-Metti "invaria1.bas" nella stessa directory di "Basic.exe"
-Lanci il Decimal Basic con Basic.exe o con un collegamento dal Desktop
-Clicchi sul pulsante 10/1000, altrimenti non funziona
-Apri il file "invaria1.bas"
-Clicchi sul pulsante RUN (freccia tipo play)
-Inserisci i dati che ti vengono richiesti (esponente, minimo e massimo)
-Aspetti e leggi gli invarianti con i singoli tempi ed al termine con il tempo totale, oppure leggi solo
  il tempo totale, il che vuol dire che non vi sono invarianti.

Il programma genera un file con dati stringa "invaria.txt" nel quale potrai leggere, a programma fermo, gli invarianti trovati (basta cliccare sul file o ti costruisci un piccolo programma di lettura).
Inoltre il programma genera i file numerici "conserva1.txt" e "conserva2.txt" nei quali vengono memorizzati i dati relativi al lavoro svolto: in caso di interruzione casuale o volontaria del lavoro,
al prossimo rilancio, questi file verranno letti ed il lavoro riprenderà da dove era stato interrotto.
Quando lanci il programma la prima volta per un nuovo esponente con nuovi minimo e massimo,
dovrai prima cancellare questi file manualmente.
Quando lanci il programma come prosecuzione di un lavoro interrotto, questi file devono esserci e per quanto riguarda i dati da inserire, che vengono richiesti al lancio del programma, questi devono essere gli stessi della prima volta.
Cosa sono minimo e massimo:
questi servono a restringere il campo della ricerca un po' ad occhio.
La ricerca degli invarianti viene effettuata sulla tipologia dei numeri generatori, i quali sono dei numeri per definizione con una quantità di cifre uguale all'esponente, che possono contenere le cifre dallo 0 al 9 in quantità variabili da 0 a B (esponente): però se prendiamo ad esempio l'esponente 39 già noto, vediamo che ogni cifra è presente almeno una volta ed al massimo 7 volte,
quindi in questo caso imponiamo il minimo a 1 ed il massimo a 7 (dovrebbero venir fuori i 2 invarianti già noti).
Certamente se non l'avessi saputo a priori, avrei potuto magari impostarli a 0 e 13, che mi sembra un range abbastanza congruo, oppure avrei potuto ampliare ancora di più l'intervallo allungando i tempi della ricerca, o volendo essere sicuri a 0 e 39.
Il programma è dotato comunque di filtri che scartano i numeri impossibili (quelli che non sono lunghi quanto l'esponente, quelli che contengono cifre in quantità non ammesse, quelli la cui somma delle potenze generano un numero di lunghezza diversa dall'esponente o generano un numero che contiene cifre in quantità diversa da quello generatore).
Insomma si tratta di vedere quanto tempo occorre per trovare gli invarianti da 39 già noti, che quindi devono venir fuori per forza, e poi passare agli esponenti superiori (come già detto attualmente non posso farlo a causa del p.c. che mi sta rompendo abbastanza).

Il programma funziona (lo puoi provare con gli esponenti bassi per sicurezza) e se avrai qualche dubbio, anche per quanto riguarda certe scelte che possono sembrare ridondanti, o per quanto riguarda l'uso del Decimal Basic, chiedimi delucidazioni.

!'Ricerca completa invarianti:genera tutte le combinazioni valide di
!' presenza cifre da 0 a 9 e le valuta direttamente.
!'Questa è una versione semplificata, per cui mancano i controlli relativi ad input
!'errati.
!'Prima di premere il pulsante di avvio per la prima volta che si sceglie un esponente,
!'cancellare dalla directory di lavoro in cui si trova "invaria1.bas" i file "conserva"
!'e "invar"

!' PRIMA DI AVVIARE SETTA IL PULSANTE 10/1000

OPTION BASE 0

DIM tabmax (9,3 TO 60) !'massimo consentito di presenze per ogni cifra
FOR m = 0 TO 9
FOR n = 3 TO 60
LET s1 = n*m^n
LET q = n
LET k = 0
DO
IF LEN(STR$(s1)) < n THEN
LET q = q - 1
LET k = k + 1
LET s1 = q* m^n
LET s2= k*9^n
LET s1 = s1 + s2
END IF
LOOP UNTIL LEN(STR$(s1)) >= n
IF LEN(STR$(s1)) =n THEN LET tabmax(m,n) = q ELSE LET tabmax(m,n) = q +1
NEXT n
NEXT m

DIM potenze(9,3 TO 60)

FOR m=1 TO 9 !'tabella delle potenze
FOR n= 3 TO 60
LET potenze(m,n)=m^n
NEXT N
NEXT M


INPUT PROMPT "inserisci esponente (min 3 - max 60) -> ":b
INPUT PROMPT "inserisci minimo presenza cifre -> ":mini
INPUT PROMPT "inserisci massimo presenza cifre -> ":maxi

DIM presenze1(9) !'presenza cifre in ogni combinazione
DIM presenze2(9) !'presenza cifre nella somma delle potenze delle combinazioni
DIM minix1(9)
DIM minix2(9)


OPEN #1:NAME "conserva1" !'valori di partenza memorizzati durante il lavoro
FOR m=0 TO 9
INPUT #1,IF MISSING THEN EXIT FOR:minix1(m)
NEXT M

OPEN #2:NAME "conserva2" !'valori di partenza memorizzati durante il lavoro
FOR m=0 TO 9
INPUT #2,IF MISSING THEN EXIT FOR:minix2(m)
NEXT M

OPEN #3:NAME "invar",ACCESS OUTPUT !'memorizza gli invarianti


LET cont1=0
LET cont2=0
FOR m = 0 TO 9
LET cont1 = cont1 + minix1(m)
LET cont2 = cont2 + minix2(m)
NEXT M

PRINT "inizio come da input -> ";
FOR m=0 TO 9
PRINT mini;
NEXT M
PRINT

!'per continuare il lavoro interrotto

LET flag=0
LET flag1=0
LET flag2=0
IF cont1>0 OR cont2>0 THEN
LET flag=1
FOR m=0 TO 9
IF minix1(m) > minix2(m) THEN
LET flag1=1
PRINT "continua lavoro da -> ";
FOR n=0 TO 9
PRINT minix1(n);
NEXT N
EXIT FOR
END IF

IF minix2(m) > minix1(m) THEN
LET flag2=1
PRINT "continua lavoro da -> ";
FOR n=0 TO 9
PRINT minix2(n);
NEXT N
EXIT FOR
END IF
NEXT M
if flag1=0 and flag2=0 then
flag1=1
flag2=1
PRINT "continua lavoro da -> ";
FOR n=0 TO 9
PRINT minix2(n);
NEXT N
end if

END IF

PRINT
PRINT
PRINT " N O N T O C C A R E"
PRINT
PRINT



LET t1 = TIME

FOR m0 = mini TO maxi
FOR m1 = mini TO maxi
FOR m2 = mini TO maxi
FOR m3 = mini TO maxi
FOR m4 = mini TO maxi
FOR m5 = mini TO maxi
FOR m6 = mini TO maxi
FOR m7 = mini TO maxi
FOR m8 = mini TO maxi
FOR m9 = mini TO maxi


LET cont = 0
LET cont = cont + m0
IF cont > b OR m0>tabmax(0,b)THEN GOTO 110
LET presenze1(0) = m0
LET cont = cont + m1
IF cont > b OR m1>tabmax(1,b)THEN GOTO 100
LET presenze1(1) = m1
LET cont = cont + m2
IF cont > b OR m2>tabmax(2,b)THEN GOTO 90
LET presenze1(2) = m2
LET cont = cont + m3
IF cont > b OR m3>tabmax(3,b)THEN GOTO 80
LET presenze1(3) = m3
LET cont = cont + m4
IF cont > b OR m4>tabmax(4,b)THEN GOTO 70
LET presenze1(4) = m4
LET cont = cont + m5
IF cont > b OR m5>tabmax(5,b)THEN GOTO 60
LET presenze1(5) = m5
LET cont = cont + m6
IF cont > b OR m6>tabmax(6,b)THEN GOTO 50
LET presenze1(6) = m6
LET cont = cont + m7
IF cont > b OR m7>tabmax(7,b)THEN GOTO 40
LET presenze1(7) = m7
LET cont = cont + m8
IF cont > b OR m8>tabmax(8,b)THEN GOTO 30
LET presenze1(8) = m8
LET cont = cont + m9
IF cont <>b OR m9>tabmax(9,b)THEN GOTO 20
LET presenze1(9) = m9


!'da qui la somma delle cifre è uguale all'esponente
!'quindi la combinazione è valida

IF flag=1 THEN
LET flag=0
IF flag1=flag2 OR flag1>flag2 THEN

LET m0=minix1(0)
LET m1=minix1(1)
LET m2=minix1(2)
LET m3=minix1(3)
LET m4=minix1(4)
LET m5=minix1(5)
LET m6=minix1(6)
LET m7=minix1(7)
LET m8=minix1(8)
LET m9=minix1(9)
FOR m=0 TO 9
LET presenze1(m)=minix1(m)
NEXT M

ELSE

LET m0=minix2(0)
LET m1=minix2(1)
LET m2=minix2(2)
LET m3=minix2(3)
LET m4=minix2(4)
LET m5=minix2(5)
LET m6=minix2(6)
LET m7=minix2(7)
LET m8=minix2(8)
LET m9=minix2(9)
FOR m=0 TO 9
LET presenze1(m)=minix2(m)
NEXT M

END IF
END IF

LET somma=0 !'fai la somma delle potenze
FOR m=1 TO 9 !'inutili le potenze di zero
LET somma=somma+potenze(m,b)*presenze1(m)
NEXT M


IF LEN(STR$(somma))<>b THEN GOTO 20 !'scarta la combinazione se il precedente risultato
!'non dà un numero lungo quanto l'esponente scelto (b)



ERASE #1
FOR x=0 TO 9
PRINT #1:presenze1(x)
NEXT X

ERASE #2
FOR x=0 TO 9
PRINT #2:presenze1(x)
NEXT X


MAT presenze2=ZER !'reinizializza presenze2()

FOR m=1 TO b !'e inserisci il numero risultante
!'espresso in quantità di cifre presenti

LET v=VAL(mid$(STR$(somma),m,1))
LET presenze2(v)=presenze2(v)+1
NEXT M

FOR m=0 TO 9 !'confronta con la combinazione
!'di partenza e scarta se non uguale

IF presenze1(m)<>presenze2(m) THEN GOTO 20
NEXT M

!'da qui la combinazione è valida ed è un invariante (somma)
!'memorizza, scrivi e calcola il tempo di elaborazione

LET t2 = TIME
LET tempo = (t2-t1)/3600
LET tempo=INT(tempo*1000)/1000
WRITE #3:STR$(somma)
PRINT "esp";b;" -> ";somma;" tempo in ore -> ";tempo

20
NEXT M9
30
NEXT M8
40
NEXT M7
50
NEXT M6
60
NEXT M5
70
NEXT M4
80
NEXT M3
90
NEXT M2
100
NEXT M1
110
NEXT M0

CLOSE #1
CLOSE #2
CLOSE #3

LET t2 = TIME
LET tempo = (t2-t1)/3600
LET tempo=INT(tempo*1000)/1000

PRINT "tempo totale: ore ="; tempo
END

Giovanni Sciortino
Non ho creato nulla di nuovo ho solo tradotto il tuo algoritmo in c ottenendo dei risultati migliori rispetto ai tempi che riporti.
Es: per trovare tutti i numeri invarianti perfetti di 4 cifre il mio programma impiega su un computer pentium 4 1400 mhz 30 millesimi di secondo, e lo stesso programma per lo stesso calcolo in un pentium 2 233 impiega 90 millesimi di secondo. Non so se ti può interessare, magari hai utilizzato computer meno veloci del mio per provare il programma comunque se t'interessa ecco il sorgente:

#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <time.h>   #define interi unsigned __int64   char cifra[200];
 
 
int main(){
 unsigned char esponente;
 printf("inserisci il numero di cifre:");
 scanf("%d",&esponente);
 DWORD t1 = GetTickCount();
 interi inizio = (unsigned long)pow(10,esponente-1
  );
 interi fine = inizio*10;
 interi i = inizio;
 while (i < fine){
  interi somma=0;
  interi j = 0;
  sprintf(cifra,"%d",i);
  while (j < esponente){
   somma = somma+(int)pow((cifra[j]-'0'),esponente);
   ++j;
  }
  if (somma == i)
   printf("%d\n",i);
  ++i;
 }
 DWORD t2 = GetTickCount();
 double a = (t2-t1);
 printf("tempo impiegato(in millesimi di secondo): %f \n", a);
 return 0;
}

Questo può essere compilato senza errori con il compilatore visual c++,oppure con la maggior parte degli altri compilatori sostituendo la riga #define interi unsigned __int64 con #define interi unsigned long long


Sito Web realizzato da Gianfranco Bo