Dépassement capacité multiplication integer [Résolu]

Messages postés
40
Date d'inscription
mardi 18 mai 2004
Dernière intervention
2 mai 2010
- - Dernière réponse : vecchio56
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
- 24 août 2005 à 19:17
Bonjour,



J'ai trois integer 64 bits :

_int64 i1,i2,i3;



Comment détecter le dépassement de capacité possible sur i3, lors d'une multiplication :

i3 = i1 * i2;



Merci.
Afficher la suite 

Votre réponse

20/31 réponses

Meilleure réponse
Messages postés
40
Date d'inscription
mardi 18 mai 2004
Dernière intervention
2 mai 2010
3
Merci
J'ai trouvé ceci par hazard dans le MSDN:



-----------------------------------

_int64 i1,i2,i3;



if (i1 > (MAX / i2) )

cout << "Dépassement";

else

i3 = i1 * i2;



---------------------------

MAX doit contenir la valeur maximale de _int64



Et ça à l'air de fonctionner.



Merci pour toutes vos réponses.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de bipcpp
Messages postés
706
Date d'inscription
mardi 30 décembre 2003
Dernière intervention
27 janvier 2009
0
Merci
salut,

si ca déborde, i3 aura la particularité d'etre inferieur à i1 ou à i2.



a+
Commenter la réponse de cosmobob
Messages postés
573
Date d'inscription
samedi 16 novembre 2002
Dernière intervention
9 avril 2008
0
Merci
Pourtant, en assembleur, il y a des flags qui changent d'états pour ce genre de chose.

Quand tu fais une opération et que le resultat vaut 0, est négatif ou
depasse la memoire, des bits du flag prennent des valeurs spécifiques.

Mais comment lire ces flags, je ne sais pas.

Ils sont surtout utiles pour les optimisations de code.
Commenter la réponse de Galmiza
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
Lire CF ici n'aurait pas de sens.
La mul sur 64 bits implique au mieux 1 mul SINON 3 mul et 2 add
Le flag sera positionné par le dernier add et donc ne voudrait rien dire.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
0
Merci
Même en cas de débordement, on ne peut pas être sûr que i3 sera inférieur à i2 et i1 (par contre le contraire est sûr), a mon avis ca dépend de la manière dont le compilo implémente la multiplication sur 64 bits
Commenter la réponse de vecchio56
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
cosmobob a bien dit inf à l'un OU l'autre.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
0
Merci
et pourquoi il serait pas supérieur au 2?
Commenter la réponse de vecchio56
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
Voila pour vecchio.
Galmiza > pas évident de dire quand overflow, sinon faut définir la règle du jeu.

mov eax, [esp+8] ; HIDWORD(x)
mov ecx, [esp+16] ; HIDWORD(y)
or ecx, eax
mov ecx, [esp+12] ; LODWORD(y)
jnz short hard
mov eax, [esp+4] ; LODWORD(x)
mul ecx
jmp short mulExit
hard:
mul ecx
mov [esp-4], eax ; SAUVE RESULTAT INTERMEDIAIRE
mov eax, [esp+4] ; LODWORD(x)
mul dword ptr[esp+16] ; HIDWORD(y)
add [esp-4], eax
mov eax, [esp+4] ; LODWORD(x)
mul ecx
add edx, [esp-4]
mulExit:
ret 16

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
vecchio, tu aurais un exemple de inférieur aux 2 ?

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
0
Merci
#include

int main()
{
unsigned __int64 a 0xFFFFFFFFF, b 0xFFFFFFFFF;
unsigned __int64 r = a * b;
if(r < a || r < b) std::cout << "débordement" << std::endl;
}

Cet exemple ne m'affiche pas "débordement"
Commenter la réponse de vecchio56
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
0
Merci
Le resultat est faux, mais est supérieur aux 2 opérandes, c'est bien ce que je cherchais, BruNews (pas inférieur comme tu as dit)
Commenter la réponse de vecchio56
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
mais pas de débordement ici, enfin ne me semble pas.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
0
Merci
a et b sont sur 36 bits chacuns, ca devait donner environ 2^72... par contre j'ai triché parce qu'il fallait pas utiliser des unsigned
Commenter la réponse de vecchio56
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
ah si ah si, OUPS.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
ok trop tard de 10 secondes...

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
706
Date d'inscription
mardi 30 décembre 2003
Dernière intervention
27 janvier 2009
0
Merci
salut,


moi j'ai pas d'overflow dans l'exemple de vecchio, et le résultat affiché est correct (vérifié avec la calculette de windows)





#include <stdio.h>


#include <stdlib.h>








int main(int argc, char* argv[])


{


unsigned __int64 a = 0xFFFFFFFF;


unsigned __int64 b = 0xFFFFFFFF;





unsigned __int64 r = a*b;





char buffer[100];


_ui64toa(r, buffer, 10);





printf("%s\n", buffer);





return 0;


}
Commenter la réponse de cosmobob
Messages postés
706
Date d'inscription
mardi 30 décembre 2003
Dernière intervention
27 janvier 2009
0
Merci
ha j'ai oublié un F non ? :p

effectivement ca foire
Commenter la réponse de cosmobob
Messages postés
6539
Date d'inscription
lundi 16 décembre 2002
Dernière intervention
22 août 2010
0
Merci
La calculette de Windows marche pas bien, pas plus de 64 bits en mode hexa, donc ca donne le même résultat que VC++, mais les deux sont faux:
Tu mets 4722366482732206260225 en décimal, tu mets en hexa puis reviens en décimal, et le on obtient 18446743936270598145 :)
Commenter la réponse de vecchio56
Messages postés
4
Date d'inscription
mardi 24 août 2004
Dernière intervention
23 août 2005
0
Merci
Pour savoir si ça dépasse ou non, tu peux convertir i1 et i2 en double et faire un test dessus.


Non ?
Commenter la réponse de gotjehiuh
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
0
Merci
Bon voila je vous soumets cela, ça a l'air cohérent, faudrait faire des tests:

__declspec(naked) __int64 __stdcall mymul64(__int64 x, __int64 y, int *overflow)
{
__asm {
mov eax, [esp+8] ; HIDWORD(x)
mov ecx, [esp+16] ; HIDWORD(y)
mov edx, [esp+20] ; *overflow
or ecx, eax
mov ecx, [esp+12] ; LODWORD(y)
mov dword ptr[edx], 0 ; overflow = 0
jnz short hard
mov eax, [esp+4] ; LODWORD(x)
mul ecx
jmp short mulExit
hard:
mov [esp-8], ebx
mul ecx
mov [esp-4], eax ; SAUVE RESULTAT INTERMEDIAIRE
xor ebx, ebx
mov eax, [esp+4] ; LODWORD(x)
mul dword ptr[esp+16] ; HIDWORD(y)
add [esp-4], eax
adc ebx, 0
mov eax, [esp+4] ; LODWORD(x)
mul ecx
add edx, [esp-4]
mov ecx, [esp+20] ; *overflow
adc ebx, 0
mov [ecx], ebx
mov ebx, [esp-8]
mulExit:
ret 20
}
}


int WINAPI WinMain(HINSTANCE h, HINSTANCE x, LPSTR ystr, int z)
{
char buf[24];
__int64 a, b;
int deborde;
a = 0xFFFFFFFFFFFFFFF;
b = 0xFFFFFFFFF;
a = mymul64(a, b, &deborde);
_i64toa(a, buf, 10);
MessageBox(0, buf, "R", 0);

if(deborde) MessageBox(0, "overflow", "R", 0);

return 0;
}

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.