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

bipcpp 40 Messages postés mardi 18 mai 2004Date d'inscription 2 mai 2010 Dernière intervention - 23 août 2005 à 18:54 - Dernière réponse : vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention
- 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

31 réponses

Meilleure réponse
bipcpp 40 Messages postés mardi 18 mai 2004Date d'inscription 2 mai 2010 Dernière intervention - 24 août 2005 à 18:40
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.

Merci bipcpp 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 93 internautes ce mois-ci

Commenter la réponse de bipcpp
cosmobob 706 Messages postés mardi 30 décembre 2003Date d'inscription 27 janvier 2009 Dernière intervention - 23 août 2005 à 19:26
0
Merci
salut,

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



a+
Commenter la réponse de cosmobob
Galmiza 573 Messages postés samedi 16 novembre 2002Date d'inscription 9 avril 2008 Dernière intervention - 23 août 2005 à 20:13
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 20:44
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
vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention - 23 août 2005 à 20:45
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 21:00
0
Merci
cosmobob a bien dit inf à l'un OU l'autre.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention - 23 août 2005 à 21:06
0
Merci
et pourquoi il serait pas supérieur au 2?
Commenter la réponse de vecchio56
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 21:07
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 21:11
0
Merci
vecchio, tu aurais un exemple de inférieur aux 2 ?

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention - 23 août 2005 à 21:15
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
vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention - 23 août 2005 à 21:16
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 21:20
0
Merci
mais pas de débordement ici, enfin ne me semble pas.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention - 23 août 2005 à 21:24
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 21:24
0
Merci
ah si ah si, OUPS.

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

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
cosmobob 706 Messages postés mardi 30 décembre 2003Date d'inscription 27 janvier 2009 Dernière intervention - 23 août 2005 à 21:43
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
cosmobob 706 Messages postés mardi 30 décembre 2003Date d'inscription 27 janvier 2009 Dernière intervention - 23 août 2005 à 21:49
0
Merci
ha j'ai oublié un F non ? :p

effectivement ca foire
Commenter la réponse de cosmobob
vecchio56 6539 Messages postés lundi 16 décembre 2002Date d'inscription 22 août 2010 Dernière intervention - 23 août 2005 à 21:56
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
gotjehiuh 4 Messages postés mardi 24 août 2004Date d'inscription 23 août 2005 Dernière intervention - 23 août 2005 à 22:18
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 23 août 2005 à 22:23
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.