OVH Cloud OVH Cloud

Exposant d'un double

5 réponses
Avatar
Garp
Bonjour,

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.

qqun a un idee ?

Merci

Fred

5 réponses

Avatar
Fabien LE LEZ
On Thu, 16 Dec 2004 23:08:21 +0100, Garp :

Mais j'imagine qu'il doit y avoir plus rapide


Pas forcément, surtout si la fonction log10 est codée en dur dans le
processeur.


--
;-)

Avatar
Falk Tannhäuser
Garp wrote:

Question C/C++ : je dois extraire l'exposant d'un double de la maniere
la plus performante possible.


man frexp

Falk

Avatar
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 :

(*reinterpret_cast< unsigned short* >( &d ) >> 4) & 0x07FF - ??

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

Avatar
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 :

(*reinterpret_cast< unsigned short* >( &d ) >> 4) & 0x07FF - ??

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)


Avatar
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


chose du genre :

(*reinterpret_cast< unsigned short* >( &d ) >> 4) & 0x07FF - ??

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