Dépassement capacité multiplication integer

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

31 réponses

bipcpp Messages postés 40 Date d'inscription mardi 18 mai 2004 Statut Membre Dernière intervention 2 mai 2010
24 août 2005 à 18:40
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.
3
cosmobob Messages postés 700 Date d'inscription mardi 30 décembre 2003 Statut Membre Dernière intervention 27 janvier 2009 4
23 août 2005 à 19:26
salut,

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



a+
0
Galmiza Messages postés 573 Date d'inscription samedi 16 novembre 2002 Statut Membre Dernière intervention 9 avril 2008 1
23 août 2005 à 20:13
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.
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 20:44
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++
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
23 août 2005 à 20:45
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
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 21:00
cosmobob a bien dit inf à l'un OU l'autre.

ciao...
BruNews, MVP VC++
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
23 août 2005 à 21:06
et pourquoi il serait pas supérieur au 2?
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 21:07
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++
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 21:11
vecchio, tu aurais un exemple de inférieur aux 2 ?

ciao...
BruNews, MVP VC++
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
23 août 2005 à 21:15
#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"
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
23 août 2005 à 21:16
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)
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 21:20
mais pas de débordement ici, enfin ne me semble pas.

ciao...
BruNews, MVP VC++
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
23 août 2005 à 21:24
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
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 21:24
ah si ah si, OUPS.

ciao...
BruNews, MVP VC++
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 21:25
ok trop tard de 10 secondes...

ciao...
BruNews, MVP VC++
0
cosmobob Messages postés 700 Date d'inscription mardi 30 décembre 2003 Statut Membre Dernière intervention 27 janvier 2009 4
23 août 2005 à 21:43
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;


}
0
cosmobob Messages postés 700 Date d'inscription mardi 30 décembre 2003 Statut Membre Dernière intervention 27 janvier 2009 4
23 août 2005 à 21:49
ha j'ai oublié un F non ? :p

effectivement ca foire
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
23 août 2005 à 21:56
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 :)
0
gotjehiuh Messages postés 4 Date d'inscription mardi 24 août 2004 Statut Membre Dernière intervention 23 août 2005
23 août 2005 à 22:18
Pour savoir si ça dépasse ou non, tu peux convertir i1 et i2 en double et faire un test dessus.


Non ?
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
23 août 2005 à 22:23
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++
0
Rejoignez-nous