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)
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
"fredatwork" <fredatwork@hotmail.com> a écrit:
"Pierre Maurette" <maurettepierre@wanadoo.fr> a écrit dans le message news:
af4lk0p4tgkdj9ndjs91bdp9jlp4kmpa4k@4ax.com...
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
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
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
fredatwork wrote:
"Pierre Maurette" <maurettepierre@wanadoo.fr> a écrit dans le message news:
af4lk0p4tgkdj9ndjs91bdp9jlp4kmpa4k@4ax.com...
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.
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
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
Arnaud Meurgues <arnaud@meurgues.non.fr.invalid> 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;
}
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
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 !
"Pierre Maurette" <maurettepierre@wanadoo.fr> a écrit dans le message de
news:ieilk0tifegse3lvsvtsa7q5uoqgvvk8ff@4ax.com...
"K. Ahausse" <anonymous@discussions.microsoft.com> a écrit:
"Philippe Guglielmetti" <newz@goulu.net> a écrit dans le message de
news:414a75d3$0$21019$5402220f@news.sunrise.ch...
"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
"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 !
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
Pierre Maurette <maurettepierre@wanadoo.fr> 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
--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
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
Pierre Maurette wrote:
Pierre Maurette <maurettepierre@wanadoo.fr> 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.
--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
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
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!) ...
17.09.2004 09:14:53
Richard Delorme <abulmo@nospam.fr> wrote in message
<414a8f27$0$15748$7a628cd7@news.club-internet.fr>
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
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!) ...
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
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!) ...
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'.
"Pierre Maurette" <maurettepierre@wanadoo.fr> a écrit dans le message de
news:31mlk0t5ugnm7bvd967sti5a6ubqjf8tbb@4ax.com...
Pierre Maurette <maurettepierre@wanadoo.fr> 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'.