Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
man frexp
Falk
kanze
Garp wrote:
Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur; int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant dans la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le format des doubles sur la machine en question, il y a toujours une possibilité de convertir l'adresse du double en pointeur vers un tableau de unsigned char (ou unsigned short sur la plupart des machines, qui aurait l'avantage que l'exposant tient sur un seul élément) et accéder directement aux bits. Sur ma machine, quelque chose du genre :
ferait l'affaire. (Il faudrait que je cherche dans la documentation pour savoir la valeur exacte qu'il faut soustraire, et j'en suis trop paresseux.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Garp wrote:
Question C/C++ : je dois extraire l'exposant d'un double de la
maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur;
int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant
directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant
dans la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le
format des doubles sur la machine en question, il y a toujours
une possibilité de convertir l'adresse du double en pointeur
vers un tableau de unsigned char (ou unsigned short sur la
plupart des machines, qui aurait l'avantage que l'exposant tient
sur un seul élément) et accéder directement aux bits. Sur ma
machine, quelque chose du genre :
Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur; int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant dans la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le format des doubles sur la machine en question, il y a toujours une possibilité de convertir l'adresse du double en pointeur vers un tableau de unsigned char (ou unsigned short sur la plupart des machines, qui aurait l'avantage que l'exposant tient sur un seul élément) et accéder directement aux bits. Sur ma machine, quelque chose du genre :
ferait l'affaire. (Il faudrait que je cherche dans la documentation pour savoir la valeur exacte qu'il faut soustraire, et j'en suis trop paresseux.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Olivier Azeau
wrote:
Garp wrote:
Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur; int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant dans la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le format des doubles sur la machine en question, il y a toujours une possibilité de convertir l'adresse du double en pointeur vers un tableau de unsigned char (ou unsigned short sur la plupart des machines, qui aurait l'avantage que l'exposant tient sur un seul élément) et accéder directement aux bits. Sur ma machine, quelque chose du genre :
ferait l'affaire. (Il faudrait que je cherche dans la documentation pour savoir la valeur exacte qu'il faut soustraire, et j'en suis trop paresseux.)
Je me souviens aussi avoir écrit des trucs dans le genre : union insideMyDouble { double d; struct fields { unsigned int sign:1; unsigned long long mantissa:52; unsigned int exponent:11; }; };
(Je ne garantis ni l'ordre, ni la taille des bitfields)
kanze@gabi-soft.fr wrote:
Garp wrote:
Question C/C++ : je dois extraire l'exposant d'un double de la
maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur;
int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant
directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant
dans la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le
format des doubles sur la machine en question, il y a toujours
une possibilité de convertir l'adresse du double en pointeur
vers un tableau de unsigned char (ou unsigned short sur la
plupart des machines, qui aurait l'avantage que l'exposant tient
sur un seul élément) et accéder directement aux bits. Sur ma
machine, quelque chose du genre :
ferait l'affaire. (Il faudrait que je cherche dans la
documentation pour savoir la valeur exacte qu'il faut
soustraire, et j'en suis trop paresseux.)
Je me souviens aussi avoir écrit des trucs dans le genre :
union insideMyDouble
{
double d;
struct fields
{
unsigned int sign:1;
unsigned long long mantissa:52;
unsigned int exponent:11;
};
};
(Je ne garantis ni l'ordre, ni la taille des bitfields)
Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur; int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant dans la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le format des doubles sur la machine en question, il y a toujours une possibilité de convertir l'adresse du double en pointeur vers un tableau de unsigned char (ou unsigned short sur la plupart des machines, qui aurait l'avantage que l'exposant tient sur un seul élément) et accéder directement aux bits. Sur ma machine, quelque chose du genre :
ferait l'affaire. (Il faudrait que je cherche dans la documentation pour savoir la valeur exacte qu'il faut soustraire, et j'en suis trop paresseux.)
Je me souviens aussi avoir écrit des trucs dans le genre : union insideMyDouble { double d; struct fields { unsigned int sign:1; unsigned long long mantissa:52; unsigned int exponent:11; }; };
(Je ne garantis ni l'ordre, ni la taille des bitfields)
kanze
Olivier Azeau wrote:
wrote:
Garp wrote:
Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur; int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant dans
la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le format des doubles sur la machine en question, il y a toujours une possibilité de convertir l'adresse du double en pointeur vers un tableau de unsigned char (ou unsigned short sur la plupart des machines, qui aurait l'avantage que l'exposant tient sur un seul élément) et accéder directement aux bits. Sur ma machine, quelque
ferait l'affaire. (Il faudrait que je cherche dans la documentation pour savoir la valeur exacte qu'il faut soustraire, et j'en suis trop paresseux.)
Je me souviens aussi avoir écrit des trucs dans le genre : union insideMyDouble { double d; struct fields { unsigned int sign:1; unsigned long long mantissa:52; unsigned int exponent:11; }; };
(Je ne garantis ni l'ordre, ni la taille des bitfields)
Le problème, c'est que le mapping (ordre, etc.) des bitfields dépend strictement de l'implémentation, et varie en fait d'une implémentation à l'autre. Sans parler du fait que toutes les implémentations ne supportent pas long long. Parmi les trois compilateurs à ma disposition, g++ fait ce que tu veux (avec :
struct Fields { unsigned int signe : 1 ; unsigned int exposent : 11 ; unsigned long long mantisse : 52 ; } ;
), Sun CC réfuse de le compiler avec un bitfield de type long long, et VC++ (6.0) le compile, mais d'une part, arrange les champs dans l'ordre inverse, et de l'autre, tronque le nombre de bits de la mantisse à 32 (sans avertissement ni erreur !) -- et puisque ça doit être le premier champs chez eux, tous les autres sont décalés.
Avec : struct Fields { unsigned int signe : 1 ; unsigned int exposent : 11 ; unsigned int mantisseFort : 32 - 12 ; unsigned int mantisseFaible : 32 ; } ; ça marche et avec Sun CC et avec g++ -- en inversant les champs (c-à-d avec mantisseFaible comme premier champ, et signe comme dernier), ça marche avec VC++.
A priori, ça doit générer le même code que ma proposition. À la suite, c'est vraiment une question de goût -- formellement, tout sauf la conversion de l'adresse en unsigned char, et l'exploitation des ces unsigned char, a un comportement indéfini, mais on est de toute façon tellement loin d'un code portable (dans les deux cas) qu'à mon avis, il ne vaut plus la peine de s'y inquièter.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Olivier Azeau wrote:
kanze@gabi-soft.fr wrote:
Garp wrote:
Question C/C++ : je dois extraire l'exposant d'un double de la
maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur;
int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant
directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant
dans
la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le
format des doubles sur la machine en question, il y a toujours une
possibilité de convertir l'adresse du double en pointeur vers un
tableau de unsigned char (ou unsigned short sur la plupart des
machines, qui aurait l'avantage que l'exposant tient sur un seul
élément) et accéder directement aux bits. Sur ma machine,
quelque
ferait l'affaire. (Il faudrait que je cherche dans la documentation
pour savoir la valeur exacte qu'il faut soustraire, et j'en suis
trop paresseux.)
Je me souviens aussi avoir écrit des trucs dans le genre :
union insideMyDouble
{
double d;
struct fields
{
unsigned int sign:1;
unsigned long long mantissa:52;
unsigned int exponent:11;
};
};
(Je ne garantis ni l'ordre, ni la taille des bitfields)
Le problème, c'est que le mapping (ordre, etc.) des bitfields dépend
strictement de l'implémentation, et varie en fait d'une
implémentation à
l'autre. Sans parler du fait que toutes les implémentations ne
supportent pas long long. Parmi les trois compilateurs à ma
disposition, g++ fait ce que tu veux (avec :
struct Fields
{
unsigned int signe : 1 ;
unsigned int exposent : 11 ;
unsigned long long mantisse : 52 ;
} ;
), Sun CC réfuse de le compiler avec un bitfield de type long long, et
VC++ (6.0) le compile, mais d'une part, arrange les champs dans l'ordre
inverse, et de l'autre, tronque le nombre de bits de la mantisse à 32
(sans avertissement ni erreur !) -- et puisque ça doit être le
premier
champs chez eux, tous les autres sont décalés.
Avec :
struct Fields
{
unsigned int signe : 1 ;
unsigned int exposent : 11 ;
unsigned int mantisseFort : 32 - 12 ;
unsigned int mantisseFaible : 32 ;
} ;
ça marche et avec Sun CC et avec g++ -- en inversant les champs
(c-à-d
avec mantisseFaible comme premier champ, et signe comme dernier), ça
marche avec VC++.
A priori, ça doit générer le même code que ma proposition. À la
suite,
c'est vraiment une question de goût -- formellement, tout sauf la
conversion de l'adresse en unsigned char, et l'exploitation des ces
unsigned char, a un comportement indéfini, mais on est de toute façon
tellement loin d'un code portable (dans les deux cas) qu'à mon avis,
il
ne vaut plus la peine de s'y inquièter.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Question C/C++ : je dois extraire l'exposant d'un double de la maniere la plus performante possible.
Ma permiere version a ete :
double val = mavaleur; int exposant = (int)log10(dval);
Mais j'imagine qu'il doit y avoir plus rapide en exploitant directement les bits d'exposant du double.
Dans la mésure où tu veux l'exposant décimal, et que l'exposant dans
la représentation des double est binaire, ce n'est pas sûr.
Si l'exposant binaire fait l'affaire, il y a frexp.
Sinon, si la portabilité n'est pas un problème, et tu connais le format des doubles sur la machine en question, il y a toujours une possibilité de convertir l'adresse du double en pointeur vers un tableau de unsigned char (ou unsigned short sur la plupart des machines, qui aurait l'avantage que l'exposant tient sur un seul élément) et accéder directement aux bits. Sur ma machine, quelque
ferait l'affaire. (Il faudrait que je cherche dans la documentation pour savoir la valeur exacte qu'il faut soustraire, et j'en suis trop paresseux.)
Je me souviens aussi avoir écrit des trucs dans le genre : union insideMyDouble { double d; struct fields { unsigned int sign:1; unsigned long long mantissa:52; unsigned int exponent:11; }; };
(Je ne garantis ni l'ordre, ni la taille des bitfields)
Le problème, c'est que le mapping (ordre, etc.) des bitfields dépend strictement de l'implémentation, et varie en fait d'une implémentation à l'autre. Sans parler du fait que toutes les implémentations ne supportent pas long long. Parmi les trois compilateurs à ma disposition, g++ fait ce que tu veux (avec :
struct Fields { unsigned int signe : 1 ; unsigned int exposent : 11 ; unsigned long long mantisse : 52 ; } ;
), Sun CC réfuse de le compiler avec un bitfield de type long long, et VC++ (6.0) le compile, mais d'une part, arrange les champs dans l'ordre inverse, et de l'autre, tronque le nombre de bits de la mantisse à 32 (sans avertissement ni erreur !) -- et puisque ça doit être le premier champs chez eux, tous les autres sont décalés.
Avec : struct Fields { unsigned int signe : 1 ; unsigned int exposent : 11 ; unsigned int mantisseFort : 32 - 12 ; unsigned int mantisseFaible : 32 ; } ; ça marche et avec Sun CC et avec g++ -- en inversant les champs (c-à-d avec mantisseFaible comme premier champ, et signe comme dernier), ça marche avec VC++.
A priori, ça doit générer le même code que ma proposition. À la suite, c'est vraiment une question de goût -- formellement, tout sauf la conversion de l'adresse en unsigned char, et l'exploitation des ces unsigned char, a un comportement indéfini, mais on est de toute façon tellement loin d'un code portable (dans les deux cas) qu'à mon avis, il ne vaut plus la peine de s'y inquièter.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34