GNT sans publicité, site mobile, fonctionnalitées exclusives...

Multiplication, comparaison et débordement

Le
Lucas Levrel
Bonjour,

Je dois comparer le produit de plusieurs int à une constante (dans une
macro). Typiquement :

#define LIMITE 512*1024*1024
int a,b,c;

if(a*b*c<LIMITE)

Comment faire ça proprement si LIMITE et le produit sont supérieurs à
INT_MAX ? Notamment :
- quel type pour LIMITE ;
- comment écririez-vous la comparaison ?

Le but étant la lisibilité et la portabilité, pas la performance.

Pour LIMITE je suppose qu'il faut opter pour long long int, parce qu'avec
unsigned int je vais buter sur 4 gigas. Mais je pourrais aussi utiliser
un flottant s'il est plus portable (une petite erreur d'arrondi n'est pas
grave dans mon contexte).

Merci.
--
LL
Lire les 15 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 3
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
JKB
Le #22598481
Le Wed, 22 Sep 2010 15:00:41 +0200,
Lucas Levrel
Bonjour,



Bonjour,

Je dois comparer le produit de plusieurs int à une constante (dans une
macro). Typiquement :

#define LIMITE 512*1024*1024
int a,b,c;
...
if(a*b*c
Comment faire ça proprement si LIMITE et le produit sont supérieurs à
INT_MAX ? Notamment :
- quel type pour LIMITE ;
- comment écririez-vous la comparaison ?

Le but étant la lisibilité et la portabilité, pas la performance.

Pour LIMITE je suppose qu'il faut opter pour long long int, parce qu'avec
unsigned int je vais buter sur 4 gigas. Mais je pourrais aussi utiliser
un flottant s'il est plus portable (une petite erreur d'arrondi n'est pas
grave dans mon contexte).



Justement, ça dépend du contexte et des valeurs a, b, et c. On peut
tout imaginer jusqu'à :

#define LIMITE ((log(512) + log(1024) + log(1024))

if ((log(a) + log(b) + log(c)) < LIMITE)
{
...
}

Bon, on suppose que a, b, et c sont strictement positifs. On peut
ajouter des valeurs absolues s'il le faut.

On peut aussi imaginer (a * b < LIMITE / c) en fonction des valeurs
relatives de a, b et c.

Il faut donc nous en dire plus sur a, b et c.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Marc Boyer
Le #22598471
Le 22-09-2010, Lucas Levrel
Bonjour,

Je dois comparer le produit de plusieurs int à une constante (dans une
macro). Typiquement :

#define LIMITE 512*1024*1024
int a,b,c;
...
if(a*b*c
Comment faire ça proprement si LIMITE et le produit sont supérieurs à
INT_MAX ? Notamment :
- quel type pour LIMITE ;
- comment écririez-vous la comparaison ?



Si on est obligé d'écrire le test
if(a*b*c<LIMITE)
on peut pas faire grand chose (à par prier pour que long long int
soit suffisant).

Sinon, le log me semble plutôt une bonne idée.

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?a...amp;id_mot0
Marc
Le #22598591
JKB wrote:

#define LIMITE ((log(512) + log(1024) + log(1024))

if ((log(a) + log(b) + log(c)) < LIMITE)



Cela apporte-t-il vraiment quelque chose comparé à :

#define LIMITE (512. * 1024 * 1024)
if ((double(a) * b * c) < LIMITE)

?

On peut aussi imaginer (a * b < LIMITE / c) en fonction des valeurs
relatives de a, b et c.



oui, remplacer la multiplication par une division est une des méthodes
usuelles dans certains contextes.
Antoine Leca
Le #22598581
Lucas Levrel écrivit :
#define LIMITE 512*1024*1024
int a,b,c;
...
if(a*b*c
Comment faire ça proprement si LIMITE et le produit sont supérieurs à
INT_MAX ? Notamment :
- quel type pour LIMITE ;



Le même que celui que donne au final la multiplication

[...] je suppose qu'il faut opter pour long long int, parce
qu'avec unsigned int je vais buter sur 4 gigas.



Bzzz ! En fait officiellement tu vas buter sur 65535.
Pour avoir une limite garantie à 4 milliards [histoire de ne pas parler
jargon], il faudrait transtyper en unsigned long ; et tant qu'à faire,
si tu es sûr d'avoir une implémentation C99, tu passeras effectivement à
long long, pour une limite garantie à 8 trillions.

Savoir si cela suffit, ou pas, est ton problème ; si cela peut ne pas
suffire (genre, tu ne sais absolument rien de a,b,c _et_ ta machine
cible pour avoir des int sur 64 bits ou plus), la solution des flottants
est effectivement plus bétonné. De plus c'est conforme C90.

Et comme le fait remarquer JKB, attention aux nombres négatifs (le fait
d'utiliser des types non signés ne calcule pas les valeurs absolues !)


Antoine
Lucas Levrel
Le #22598621
Le 22 septembre 2010, JKB a écrit :

Bon, on suppose que a, b, et c sont strictement positifs.



Ah oui, j'ai oublié de le préciser (je voulais le faire mais ça a fait
pschit).

On peut aussi imaginer (a * b < LIMITE / c) en fonction des valeurs
relatives de a, b et c.

Il faut donc nous en dire plus sur a, b et c.



Effectivement, je n'avais pas pensé à cette division ! Justement,
c=sizeof(truc), ça paraît même logique de le mettre du même côté que
la constante LIMITE.

Actuellement, a00, b=2^16, c$. Dans ce cas de figure, avec LIMITE un
multiple de 2^(20 au moins), évidemment a*c<LIMITE/b donne un résultat
exact.

Il me reste une question : est-ce que tout compilateur va calculer
la constante 4*1024*1024*1024/65536 sans débordement ?

--
LL
Publicité
Suivre les réponses
Poster une réponse
Anonyme