OVH Cloud OVH Cloud

[if] plusieurs variables..

35 réponses
Avatar
Jean-Philippe Provost
Bonjour,

J'aimerais savoir comment je peut faire pour faire afficher le plus
petit et le plus grand de 3 nombres?

if ( nombre1 < nombre2, nombre3 )

Bref, vs comprenez le principe?

Dois-je faire cela 1 a 1 ou il existe un moyen (fonction) pour combiner
mes variables nombre*?

A++

10 réponses

1 2 3 4
Avatar
fredatwork
"Pierre Maurette" a écrit dans le message news:

La première forme doit pouvoir s'écrire:
i -= (i % 2 == 0);


Question stupide mais est-on assuré que (i % 2 == 0) renvoie 1 quand il ne
renvoie pas 0 ?

Avatar
Arnaud Meurgues
fredatwork wrote:

Question stupide mais est-on assuré que (i % 2 == 0) renvoie 1 quand il ne
renvoie pas 0 ?


Oui. Que pourrait-il renvoyer d'autre ?

--
Arnaud
(Supprimez les geneurs pour me répondre)

Avatar
Pierre Maurette
"fredatwork" a écrit:

"Pierre Maurette" a écrit dans le message news:

La première forme doit pouvoir s'écrire:
i -= (i % 2 == 0);


Question stupide mais est-on assuré que (i % 2 == 0) renvoie 1 quand il ne
renvoie pas 0 ?
Oui, en C comme en C++. Une expression logique (à base d'opérateurs de

comparaison par exemple) est toujours évaluée à 0 ou 1. Mais toute
expression non fausse (!= 0) est comprise comme vraie par les
instructions de test. Si vous avez une expression "booléenne" E
d'origine douteuse, vous pouvez la normaliser par
E = (E != 0);
par exemple.
Mais l'affectation d'un "booléen" à un entier n'est pas une des
gloires du langage...
--
Pierre


Avatar
Alexandre Bacquart
fredatwork wrote:

"Pierre Maurette" a écrit dans le message news:


La première forme doit pouvoir s'écrire:
i -= (i % 2 == 0);


Question stupide mais est-on assuré que (i % 2 == 0) renvoie 1 quand il ne
renvoie pas 0 ?


Quand ils sont convertis en entiers, true donne 1 et false donne 0.
C'est la norme. Si ton compilo dit C++ (ou C) renvoit autre chose, tu as
le droit (et même le devoir) de cliquer sur son executable et de faire
SHIFT + SUPPR et ENTER.

--
Tek


Avatar
Pierre Maurette
Arnaud Meurgues a écrit:

fredatwork wrote:

Question stupide mais est-on assuré que (i % 2 == 0) renvoie 1 quand il ne
renvoie pas 0 ?


Oui. Que pourrait-il renvoyer d'autre ?
Je ne sais pas, 0 ou une valeur non nulle par exemple. Une comparaison

renvoie 1 ou 0 selon la norme, mais je pense qu'il vaut mieux le
vérifier que le déclarer "évident". Que penser de:

bool b1 = true;
bool b2 = true;

++b2;

if(b1 == b2)
{
std::cout << "b1 et b2 sont simultanément V ou F" << std::endl;
}
else
{
std::cout << "b1 et b2 sont inverses" << std::endl;
}

if(b1)
{
std::cout << "b1 est V" << std::endl;
}
else
{
std::cout << "b1 est F" << std::endl;
}

if(b2)
{
std::cout << "b2 est V" << std::endl;
}
else
{
std::cout << "b2 est F" << std::endl;
}

?
--
Pierre


Avatar
K. Ahausse
"Pierre Maurette" a écrit dans le message de
news:
"K. Ahausse" a écrit:


"Philippe Guglielmetti" a écrit dans le message de
news:414a75d3$0$21019$
"Jean-Noël Mégoz" a écrit
Soit une variable i entière et initialisée.
Je veux que i soit impair. S'il est pair, je veux le ramener à
l'impair

immédiatement inférieur. Je vois deux façons d'écrire ça :
-> if(i % 2 == 0) i--; // foin des accolades, c'est un
exemple !

-> i -= 1 - (i % 2);



i -= (~i & 1) , ça marche et en plus l'optimisation est simplissime.

Exemple sur 80x86 :

mov eax, i // charger variable i dans accu
mov ecx, eax // copie de i dans le registre ecx
not ecx
and ecx,1
sub eax, ecx
mov i, eax // sauver accu dans variable i

--i |= 1 , ça marche et en plus l'optimisation est hyper simplissime.


Exemple sur 80x86 :
dec i // variable - 1 -> variable
or 1, 1 // forçage du LSB de variable


Waouf ! L'ouvre d'un magicien !




Avatar
Pierre Maurette
Pierre Maurette a écrit:
[...]
--i |= 1 , ça marche et en plus l'optimisation est hyper simplissime.

Exemple sur 80x86 :
dec i // variable - 1 -> variable
or 1, 1 // forçage du LSB de variable
Les commentaires sont stupides :

a = b; // la valeur de b dans a ;-)

Comme c'est à la fois obscur et non portable, je préfère:

#define x86_impair_inf(var) asm dec (var);asm or (var), 1;

OK ,c'est une macro, et un borlandisme, qui plus est, l'enchaînement
d'une séquence asm (_asm, __asm) sous une macro étant parfois
imprévisible.

Celle-ci fonctionne avec une donnée char, short ou long. Mais c'est
limite foireux.
--
Pierre

Avatar
Alexandre Bacquart
Pierre Maurette wrote:

Pierre Maurette a écrit:
[...]

--i |= 1 , ça marche et en plus l'optimisation est hyper simplissime.

Exemple sur 80x86 :
dec i // variable - 1 -> variable
or 1, 1 // forçage du LSB de variable


Les commentaires sont stupides :
a = b; // la valeur de b dans a ;-)


Mais ton optimisation est meilleure. Cependant, en général pour ce genre
de truc, si c'est critique, il vaut mieux essayer de privilégier une
implémentation du genre "toujours pair inférieur" ou "toujours impair
supérieur", ainsi il n'y a qu'une opération à faire, un "and" ou un "or"
respectivement.


--
Tek


Avatar
Philippe Guglielmetti
17.09.2004 09:14:53
Richard Delorme wrote in message
<414a8f27$0$15748$

la seconde, et très nettement car il n'y a pas de test et donc
pas de


rupture dans le flux d'instructions et donc le pipeline du proc
reste


bien plein.
On peut d'ailleurs encore faire encore mieux: i-= 1-(i&1); qui
ne


fait pas de division.
pour la lisibilité, tu peux faire:
i-= 1-(i&1); // force i pair à l'impair inférieur


Ce n'est pas évident, les CPU modernes ont une instruction pour
effectuer des MOV conditionnels, et g++ en profite sur mon athlon,
voilà

l'assembleur qu'il produit, dans les trois cas :

g++ -O2 -frame-omit-pointer -march=athlon-XP

// if (i % 2 == 0) i--;
movl 4(%esp), %eax // %eax = i
leal -1(%eax), %edx // %edx = i-1
testb $1, %al // %eax est impair ?
cmove %edx, %eax // %eax = %edx> ...
...
A mon avis, mais je n'ai pas mesuré, la première forme est la plus
rapide, car le CPU peut sans doute effectuer les instructions 2 et
3 en

parallèle.

Cela dépend-il du compilateur ?


non, je ne crois pas qu'il y ait des compilos assez malins pour
"convertir" le source de la première méthode en exécutable sans
test


et sans division.


Si, il y a au moins g++, icc (Intel C/C++ compiler), et sans doute
la

plupart des compilateurs actuels.
wow, je connaissais pas le cmove, et j'admire les progrès des

optimiseurs!
j'avais tort (ça arrive... rarement... ;-)
S'abtenir de toute optimisation manuelle est, sur cet exemple
particulier et comme bien souvent, la solution la plus rapide. J'en

profite pour rappeler les trois points fondamentaux de
l'optimisation :

1 - Ne pas optimiser
2 - Ne pas optimiser
3 - Pour expert seulement : ne pas optimiser encore.
J'approuve, mais 4a ne doit pas être une excuse pour programmer comme

un cochon. Je viens de trouver du code qui, pour trouver la valeur
maxi dans une liste la trie puis garde la première valeur (et jette
le reste!) ...



Avatar
K. Ahausse
"Pierre Maurette" a écrit dans le message de
news:
Pierre Maurette a écrit:
[...]
--i |= 1 , ça marche et en plus l'optimisation est hyper simplissime.

Exemple sur 80x86 :
dec i // variable - 1 -> variable
or 1, 1 // forçage du LSB de variable
Les commentaires sont stupides :

a = b; // la valeur de b dans a ;-)

Comme c'est à la fois obscur et non portable, je préfère:

#define x86_impair_inf(var) asm dec (var);asm or (var), 1;

OK ,c'est une macro, et un borlandisme, qui plus est, l'enchaînement
d'une séquence asm (_asm, __asm) sous une macro étant parfois
imprévisible.

Celle-ci fonctionne avec une donnée char, short ou long. Mais c'est
limite foireux.


P'tain, du 'foireux' aussi éblouissant, j'en redemande sans 'limite'.


1 2 3 4