Accueil > > > NOMBRE NARCISSIQUE (WIN32, ASM)
NOMBRE NARCISSIQUE (WIN32, ASM)
Information sur la source
Description
Bonjour,
Je vous presente (sans pretention aucune), un code (C/ASM) permettant de savoir si un nombre est narcissique ou pas.
Nombre narcissique : http://membres.lycos.fr/villemingerard/Formes/Narc issi.htm
J'ai vu une autre definition qui reprenait celle ci, mais qui envisageait aussi le cas ou la somme des factorielles des chiffres (ou parties de chiffres) d'un nombre etait egale a ce nombre. (cf lien precedent, vous comprendrez mieux). Etant donné qu'au point de vu programmation, verifier les factorielles etc.. ne m'apprenait rien (reprise du code sur les puissance, cf lien ;)), je ne l'ai pas codé.
Si j'ai fait ce code en ASM, c'est juste une petite revanche envers moi meme, car je suis, un jour, tombé sur cet exercice, et j'ai perdu mon temps a le coder, alors que c'etait simple...Enfin bon, certains me comprendront ;)
Je souhaite bien entendu aussi avoir des avis, surtout negatif pour me dire ce qui ne va pas.
Source
- #include <windows.h>
- #include "resource.h"
-
- WNDPROC oldEditProc;
- HINSTANCE hInstance;
-
- /*__declspec(naked) void __stdcall PuissFPU(int n, int exp)
- {
- __asm {
- mov ecx, [esp + 8] //eax == exp
- fild dword ptr[esp + 4] //empile n, ST(1) == n
- dec ecx
- jle Fin
- fld ST //empile n, ST(0) == n, Contiendra le resultat
- Deb:
- fmul ST(1), ST
- dec ecx
- test ecx, ecx
- jne Deb
- fstp ST
- Fin:
- fistp dword ptr[esp - 4]
- mov ecx, [esp - 4]
- ret 8
- }
- }*/
-
- //Resultat renvoyé dans ecx
- __declspec(naked) void __fastcall Puiss(int n, int exp)
- {
-
- __asm {
- mov eax, ecx
- dec edx
- jle End
- Deb:
- imul ecx, eax
- dec edx
- test edx, edx
- jne Deb
- End:
- ret 0
- }
- }
-
- int __stdcall len(int n)
- {
- if (n >= 1000000000) return 10;
- if (n >= 100000000) return 9;
- if (n >= 10000000) return 8;
- if (n >= 1000000) return 7;
- if (n >= 100000) return 6;
- if (n >= 10000) return 5;
- if (n >= 1000) return 4;
- if (n >= 100) return 3;
- if (n >= 10) return 2;
-
- return 1;
- }
-
- __declspec(naked) int __fastcall sPuiss(int n, int exp)
- {
- __asm {
- mov eax, ecx
- dec edx
- Deb:
- imul eax, ecx
- dec edx
- test edx, edx
- jne Deb
- ret 0
- }
- }
-
- int Narcissique(int n)
- {
- int lSomme, lSommePrec, lTemp;
- int i, j, iTaille, exp, iPuissDix = 10;
-
- iTaille = len(n);
-
- for (exp = 2; exp < 32; ++exp) {
- iPuissDix = 10;
- for (i = 1; i < iTaille; ++i) {
- if (iTaille % i) goto EndFor;
- lTemp = n;
- lSomme = 0;
- while (lTemp) {
- lSomme += sPuiss(lTemp % iPuissDix, exp);
- lTemp /= iPuissDix;
- }
- if (lSomme == n) return 1;
- if (lSomme == lSommePrec) break;
- if (lSomme > n && i == 1) return 0;
- if (lSomme > n) break;
- lSommePrec = lSomme;
- EndFor:
- iPuissDix *= 10;
- }
- }
-
- return 0;
- }
-
- //0 < Exp <= 4
- //lTemp dans eax
- //Modulo dans ecx
- //Restaure edx
- __declspec(naked) void __fastcall asmDivide(int Exp, int lTemp)
- {
- __asm {
- mov eax, edx
-
- cmp ecx, 1
- jne L1
- mov [esp - 4], edx
- //Division par 10
- mov edx, 3435973837
- mul edx
- shr edx, 3
- //Modulo (lTemp - (Resultat * 10))
- mov eax, edx
- mov ecx, edx
- shl eax, 3
- shl ecx, 1
- add eax, ecx
- mov ecx, [esp - 4]
- sub ecx, eax
- mov eax, edx
- ret 0
- L1:
- cmp ecx, 2
- jne L2
- mov [esp - 4], edx
- //100
- mov edx, 2748779069
- inc eax
- mul edx
- shr edx, 6
- //Modulo (lTemp - (Resultat * 100))
- mov eax, edx
- mov ecx, edx
- mov edx, 100
- mul edx
- mov edx, ecx
- mov ecx, [esp - 4]
- sub ecx, eax
- mov eax, edx
- ret 0
- L2:
- cmp ecx, 3
- jne L3
- mov [esp - 4], edx
- //1000
- mov edx, 2199023256
- mul edx
- shr edx, 9
- //Modulo (lTemp - (Resultat * 1000))
- mov eax, edx
- mov ecx, edx
- mov edx, 1000
- mul edx
- mov edx, ecx
- mov ecx, [esp - 4]
- sub ecx, eax
- mov eax, edx
- ret 0
- L3:
- cmp ecx, 4
- jne L4
- mov [esp - 4], edx
- //10000
- mov edx, 3518437209
- mul edx
- shr edx, 13
- //Modulo (lTemp - (Resultat * 10000))
- mov eax, edx
- mov ecx, edx
- mov edx, 10000
- mul edx
- mov edx, ecx
- mov ecx, [esp - 4]
- sub ecx, eax
- mov eax, edx
- ret 0
- L4:
- xor eax, eax
- xor ecx, ecx
- ret 0
- }
- }
-
- __declspec(naked) int __stdcall asmNarcissique(int n)
- {
- //(ESP) => iTaille
- //(ESP + 4) => exp
- //(ESP + 8) => i
- //(ESP + 12) => lSommePrec
- //(ESP + 24) => n
- __asm {
- mov edx, [esp + 4]
- push esi
- push edi
- push ebx
- lea esi, [esp - 16]
- mov esp, esi
- xor ecx, ecx
- mov eax, 1
- mov [esi + 4], ecx
- mov [esi + 8], ecx
- mov ecx, 0FFFFFFFFh
- mov [esi + 12], ecx ;on initialise avec la plus grande valeur possible.
- push edx
- call len ;Taille du nombre
- ;shr eax, 1
- mov [esi], eax ;sauve taille sur la pile
- DebExp:
- mov eax, [esi + 4] ;exp
- inc eax
- cmp eax, 32
- jg ret0
- xor ecx, ecx
- mov [esi + 4], eax
- mov [esi + 8], ecx
- DebTaille:
- mov ecx, [esi + 8] ;i
- mov eax, [esi] ;iTaille
- inc ecx
- mov [esi + 8], ecx ;sauve i
- shr eax, 1
- cmp ecx, eax
- jg DebExp
- mov eax, [esi]
- xor edx, edx
- div ecx
- test edx, edx ;teste 'modulo' qui est dans edx
- jne DebTaille
- mov edi, [esi + 32] ;n
- xor ebx, ebx ;iSomme == 0
- WhileTmp: ;edi == lTemp
- test edi, edi
- jz Comp
- mov edx, edi
- call asmDivide ;lTemp == eax, Modulo == ecx
- mov edx, [esi + 4]
- mov edi, eax
- call Puiss ;ecx == resultat
- add ebx, ecx
- mov ecx, [esi + 8] ;ressort i de la stack
- jmp WhileTmp
- mov [esi + 12], ebx ;SommePrec
- Comp:
- mov eax, [esi + 32]
- cmp ebx, eax ; if (Somme == n) return 1;
- jg TestI
- jne C1
- mov eax, 1
- add esp, 16
- pop ebx
- pop edi
- pop esi
- ret 4
- TestI:
- cmp ecx, 1
- jne DebExp
- jmp ret0
- C1:
- mov eax, [esi + 12]
- cmp edx, eax
- jne DebTaille
- ret0:
- xor eax, eax
- add esp, 16
- pop ebx
- pop edi
- pop esi
- ret 4
- }
- }
-
- char szBuffer[16];
-
- LRESULT CALLBACK EditProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
- {
- if (WM_CHAR == message) {
- if ((wparam < 48 || wparam > 57) && wparam != VK_BACK) { MessageBeep(0); return 0; }
- if (szBuffer[0]) {
- szBuffer[0] = 0;
- SetDlgItemText(GetParent(hwnd), IDST_NARC, szBuffer);
- }
- }
-
- return CallWindowProc(oldEditProc, hwnd, message, wparam, lparam);
- }
-
- BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
- {
- int iNarc = 0;
-
- switch (message) {
- case WM_INITDIALOG:
- SetClassLong(hwnd, GCL_HICON, (long)LoadIcon(0, IDI_APPLICATION));
- oldEditProc = SetWindowLong(GetDlgItem(hwnd, IDEC_NARC), GWL_WNDPROC, (long)EditProc);
- SendMessage(GetDlgItem(hwnd, IDEC_NARC), EM_SETLIMITTEXT, 10, 0);
- PostMessage(hwnd, WM_NEXTDLGCTL, GetDlgItem(hwnd, IDEC_NARC), 1);
- return 0;
- case WM_COMMAND:
- if (IDCANCEL == wparam) {
- EndDialog(hwnd, 0);
- } else if (IDOK == wparam) {
- int i = 0;
-
- GetDlgItemText(hwnd, IDEC_NARC, szBuffer, 10);
- iNarc = atoi(szBuffer);
-
- if (!asmNarcissique(iNarc)) *((DWORD *)szBuffer) = 0x004E4F4E; //"NON"
- else *((DWORD *)szBuffer) = 0x0049554F; //"OUI"
- SetDlgItemText(hwnd, IDST_NARC, szBuffer);
- }
- return 0;
- }
-
- return 0;
- }
-
- int WINAPI WinMain(HINSTANCE hInst, HINSTANCE p, LPSTR q, int r)
- {
- hInstance = hInst;
- DialogBoxParam(hInst, (LPCTSTR)IDD_NARC, 0, DlgProc, 0);
- return 0;
- }
#include <windows.h>
#include "resource.h"
WNDPROC oldEditProc;
HINSTANCE hInstance;
/*__declspec(naked) void __stdcall PuissFPU(int n, int exp)
{
__asm {
mov ecx, [esp + 8] //eax == exp
fild dword ptr[esp + 4] //empile n, ST(1) == n
dec ecx
jle Fin
fld ST //empile n, ST(0) == n, Contiendra le resultat
Deb:
fmul ST(1), ST
dec ecx
test ecx, ecx
jne Deb
fstp ST
Fin:
fistp dword ptr[esp - 4]
mov ecx, [esp - 4]
ret 8
}
}*/
//Resultat renvoyé dans ecx
__declspec(naked) void __fastcall Puiss(int n, int exp)
{
__asm {
mov eax, ecx
dec edx
jle End
Deb:
imul ecx, eax
dec edx
test edx, edx
jne Deb
End:
ret 0
}
}
int __stdcall len(int n)
{
if (n >= 1000000000) return 10;
if (n >= 100000000) return 9;
if (n >= 10000000) return 8;
if (n >= 1000000) return 7;
if (n >= 100000) return 6;
if (n >= 10000) return 5;
if (n >= 1000) return 4;
if (n >= 100) return 3;
if (n >= 10) return 2;
return 1;
}
__declspec(naked) int __fastcall sPuiss(int n, int exp)
{
__asm {
mov eax, ecx
dec edx
Deb:
imul eax, ecx
dec edx
test edx, edx
jne Deb
ret 0
}
}
int Narcissique(int n)
{
int lSomme, lSommePrec, lTemp;
int i, j, iTaille, exp, iPuissDix = 10;
iTaille = len(n);
for (exp = 2; exp < 32; ++exp) {
iPuissDix = 10;
for (i = 1; i < iTaille; ++i) {
if (iTaille % i) goto EndFor;
lTemp = n;
lSomme = 0;
while (lTemp) {
lSomme += sPuiss(lTemp % iPuissDix, exp);
lTemp /= iPuissDix;
}
if (lSomme == n) return 1;
if (lSomme == lSommePrec) break;
if (lSomme > n && i == 1) return 0;
if (lSomme > n) break;
lSommePrec = lSomme;
EndFor:
iPuissDix *= 10;
}
}
return 0;
}
//0 < Exp <= 4
//lTemp dans eax
//Modulo dans ecx
//Restaure edx
__declspec(naked) void __fastcall asmDivide(int Exp, int lTemp)
{
__asm {
mov eax, edx
cmp ecx, 1
jne L1
mov [esp - 4], edx
//Division par 10
mov edx, 3435973837
mul edx
shr edx, 3
//Modulo (lTemp - (Resultat * 10))
mov eax, edx
mov ecx, edx
shl eax, 3
shl ecx, 1
add eax, ecx
mov ecx, [esp - 4]
sub ecx, eax
mov eax, edx
ret 0
L1:
cmp ecx, 2
jne L2
mov [esp - 4], edx
//100
mov edx, 2748779069
inc eax
mul edx
shr edx, 6
//Modulo (lTemp - (Resultat * 100))
mov eax, edx
mov ecx, edx
mov edx, 100
mul edx
mov edx, ecx
mov ecx, [esp - 4]
sub ecx, eax
mov eax, edx
ret 0
L2:
cmp ecx, 3
jne L3
mov [esp - 4], edx
//1000
mov edx, 2199023256
mul edx
shr edx, 9
//Modulo (lTemp - (Resultat * 1000))
mov eax, edx
mov ecx, edx
mov edx, 1000
mul edx
mov edx, ecx
mov ecx, [esp - 4]
sub ecx, eax
mov eax, edx
ret 0
L3:
cmp ecx, 4
jne L4
mov [esp - 4], edx
//10000
mov edx, 3518437209
mul edx
shr edx, 13
//Modulo (lTemp - (Resultat * 10000))
mov eax, edx
mov ecx, edx
mov edx, 10000
mul edx
mov edx, ecx
mov ecx, [esp - 4]
sub ecx, eax
mov eax, edx
ret 0
L4:
xor eax, eax
xor ecx, ecx
ret 0
}
}
__declspec(naked) int __stdcall asmNarcissique(int n)
{
//(ESP) => iTaille
//(ESP + 4) => exp
//(ESP + 8) => i
//(ESP + 12) => lSommePrec
//(ESP + 24) => n
__asm {
mov edx, [esp + 4]
push esi
push edi
push ebx
lea esi, [esp - 16]
mov esp, esi
xor ecx, ecx
mov eax, 1
mov [esi + 4], ecx
mov [esi + 8], ecx
mov ecx, 0FFFFFFFFh
mov [esi + 12], ecx ;on initialise avec la plus grande valeur possible.
push edx
call len ;Taille du nombre
;shr eax, 1
mov [esi], eax ;sauve taille sur la pile
DebExp:
mov eax, [esi + 4] ;exp
inc eax
cmp eax, 32
jg ret0
xor ecx, ecx
mov [esi + 4], eax
mov [esi + 8], ecx
DebTaille:
mov ecx, [esi + 8] ;i
mov eax, [esi] ;iTaille
inc ecx
mov [esi + 8], ecx ;sauve i
shr eax, 1
cmp ecx, eax
jg DebExp
mov eax, [esi]
xor edx, edx
div ecx
test edx, edx ;teste 'modulo' qui est dans edx
jne DebTaille
mov edi, [esi + 32] ;n
xor ebx, ebx ;iSomme == 0
WhileTmp: ;edi == lTemp
test edi, edi
jz Comp
mov edx, edi
call asmDivide ;lTemp == eax, Modulo == ecx
mov edx, [esi + 4]
mov edi, eax
call Puiss ;ecx == resultat
add ebx, ecx
mov ecx, [esi + 8] ;ressort i de la stack
jmp WhileTmp
mov [esi + 12], ebx ;SommePrec
Comp:
mov eax, [esi + 32]
cmp ebx, eax ; if (Somme == n) return 1;
jg TestI
jne C1
mov eax, 1
add esp, 16
pop ebx
pop edi
pop esi
ret 4
TestI:
cmp ecx, 1
jne DebExp
jmp ret0
C1:
mov eax, [esi + 12]
cmp edx, eax
jne DebTaille
ret0:
xor eax, eax
add esp, 16
pop ebx
pop edi
pop esi
ret 4
}
}
char szBuffer[16];
LRESULT CALLBACK EditProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
if (WM_CHAR == message) {
if ((wparam < 48 || wparam > 57) && wparam != VK_BACK) { MessageBeep(0); return 0; }
if (szBuffer[0]) {
szBuffer[0] = 0;
SetDlgItemText(GetParent(hwnd), IDST_NARC, szBuffer);
}
}
return CallWindowProc(oldEditProc, hwnd, message, wparam, lparam);
}
BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
int iNarc = 0;
switch (message) {
case WM_INITDIALOG:
SetClassLong(hwnd, GCL_HICON, (long)LoadIcon(0, IDI_APPLICATION));
oldEditProc = SetWindowLong(GetDlgItem(hwnd, IDEC_NARC), GWL_WNDPROC, (long)EditProc);
SendMessage(GetDlgItem(hwnd, IDEC_NARC), EM_SETLIMITTEXT, 10, 0);
PostMessage(hwnd, WM_NEXTDLGCTL, GetDlgItem(hwnd, IDEC_NARC), 1);
return 0;
case WM_COMMAND:
if (IDCANCEL == wparam) {
EndDialog(hwnd, 0);
} else if (IDOK == wparam) {
int i = 0;
GetDlgItemText(hwnd, IDEC_NARC, szBuffer, 10);
iNarc = atoi(szBuffer);
if (!asmNarcissique(iNarc)) *((DWORD *)szBuffer) = 0x004E4F4E; //"NON"
else *((DWORD *)szBuffer) = 0x0049554F; //"OUI"
SetDlgItemText(hwnd, IDST_NARC, szBuffer);
}
return 0;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE p, LPSTR q, int r)
{
hInstance = hInst;
DialogBoxParam(hInst, (LPCTSTR)IDD_NARC, 0, DlgProc, 0);
return 0;
}
Conclusion
J'ai codé la version FPU de la fonction Puissance, mais elle est beaucoup plus lente que la version avec registres generaux.
Le code ASM est un petit peu (mais notablement) plus rapide que le code C avec toutes optimisations (de VC++ ;)).
Historique
- 28 mars 2005 09:14:43 :
- Rectification de la fonction C.
- 02 avril 2005 14:49:24 :
- Prise en compte des conseils de Brunews, je n'ai malheureusement pas eu le temps de tester.
Il y a une instruction "div", mais elle me permet de gagner du temps (evite plusieurs boucles) et est necessaire pour ne pas renvoyer de faux resultats.
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
MATRICE TEMPLATEMATRICE TEMPLATE par hjr2610
Cliquez pour lire la suite par hjr2610 RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|