OVH Cloud OVH Cloud

std::numeric_limits::min()

38 réponses
Avatar
Alexis Guillaume
Bonjour à tous.

J'aimerais comprendre pourquoi sur mon système (gcc 3.3)
std::numeric_limits<double>::min() vaut 2.22507e-308. Cela me dérange
parce qu'intuitivement je pensais que le minimum serait l'opposé
de std::numeric_limits<double>::max() et que la valeur remarquable
2.22507e-308 aurait un nom spécifique.

Quelles sont les raisons de ce choix ? Je le te trouve étrange dans la
mesure ou la simple fonction suivante ne marche pas avec les double :

template <typename T>
T max( T const * begin, T const * end ) {
T max = std::numeric_limits<T>::min();
while (begin != end) {
if (*begin >= max) max = *begin;
++begin;
}
return max;
}

int main() {
unsigned int t1[] = { 1, 2, 4, 3 };
int t2[] = { -1000, -200, -1, -10 };
double t3[] = { -1, -2, -3, -4 };

std::cout << max(t1, t1 + 4) << "\n" << max(t2, t2 + 4)
<< "\n" << max(t3, t3 + 4) << std::endl;
}

Résultat :
4
-1
2.22507e-308

--
Alexis Guillaume
<http://cowsoft.free.fr> : ressources universitaires en vrac

"Il est minuit. La pluie fouette les vitres."

8 réponses

1 2 3 4
Avatar
kanze
Gabriel Dos Reis wrote in message
news:...
"Vincent Lascaux" writes:

| > | Et est ce que -std::numeric_limits<T>::max() = > | > | std::numeric_limits<T>::min() pour T char, short, int, long (et
| > | les autres si j'en oublie) ?

| > Non. Sur des machines à complément à 2, ce n'est certainement pas
| > le cas.

| Donc l'idée de prendre -std::numeric_limits<double>::max() pour
| représenter une valeur infinie plus petite que toute autre valeur
| n'est pas une idée

Et accessoirement, -std::numeric_limits<double>::max() n'est pas une
valeur infinie. Alors l'utiliser comme si elle en était une n'est
définitivement pas une bonne idée.


Alors, pour une fonction pour trouver le maximum, est-ce que tu penses
que quelque chose du genre :

template< typename FwdIter >
std::iterator_traits< FwdIter >::value_type
findMax( FwdIter begin, FwdIter end )
{
typedef std::iterator_traits< FwdIter >::value_type
T ;
T result
= ( std::numeric_limits< T >::is_integer
? std::numeric_limits< T >::min()
: std::numeric_limits< T >::has_infinity
? - std::numeric_limits< T >::infinity()
: - std::numeric_limits< T >::max() ) ;
while ( begin != end ) {
if ( *begin > result ) {
result = *begin ;
}
++ begin ;
}
return result ;
}

ferait l'affaire ? Est-ce qu'il y a des solutions plus simple ? Ou
est-ce qu'il y a encore des points auxquels je n'ai pas pensé.

(Et en passant -- j'ai bricolé un peu dans ma configuration. Est-ce que
les accents passent correctement de nouveau ?)

--
James Kanze GABI Software
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
kanze
Gabriel Dos Reis wrote in message
news:...
James Kanze writes:

| Gabriel Dos Reis writes:

| |> writes:

| |> | Gabriel Dos Reis wrote in message
| |> | news:...
| |> | > Alexis Guillaume writes:

| |> | > | J'aimerais comprendre pourquoi sur mon systeme (gcc 3.3)
| |> | > | std::numeric_limits<double>::min() vaut 2.22507e-308.

| |> | > Parce que la norme demande que ce soit la plus petite valeur
| |> | > positive.

| |> | C'est sans doute ce qu'on a voule, mais ce n'est pas ce que
| |> | dit en fait le texte normatif. Tout ce qu'il dit, c'est «
| |> | minimum finite value », avec une exception seulement pour des
| |> | types flottants avec dénormalisation ! Or, si son flottant n'a
| |> | pas de dénormalisation, ça m'étonnerait que la valeur minimum
| |> | finie ne soit pas négative.

| |> Tu connais une implémentation dans le monde réel où c'est le cas ?

| Où quoi c'est le cas ?

std::numeric_limits<double>::min() est négatif. C'est le point crucial.
Le reste, c'est de la distraction.


Du point de vue pratique, d'accord. En fait, toute les implémentations
font ce qu'on attend, sans tenir compte de la norme.

Enfin, je crois. Parce que je n'ai pas eu l'occasion d'utiliser le C++
sur des machines autres que IEEE.

| Que l'implémentation n'a pas de dénormalisation : c'est le cas même
| de la plupart des formats flottants que je connais -- sur les gros
| IBM, les PDP-11 et les Vax d'avant IEEE...

Voir ci-dessus.


Il y a ce que les implémentations font, et il y a ce que la norme dit.

| |> | En fait, d'après les valeurs qu'il a, je suppose qu'il a IEEE.
| |> | Donc, des flottants avec dénormalisation. Et l'exception
| |> | s'applique. Mais je n'arrive pas à est ce qu'ils ont écrit.

| |> Si ton interprétation ne colle pas avec la réalité, change
| |> d'interprétation :-)

| Je n'interprète rien. Je répète simplement ce que la norme dit.

Non, tu répètes simplement ce que tu as dit sur
comp.lang.c++.moderated ou cpmp.std.c++ sans pour autant suscité une
fièvre corrective de la part des implémenteurs ou des gens qui ont
maintiennent cette partie de la norme :-)


D'accord, j'ai compris. On s'en fout de ce que dit la norme, dans la
mésure que les implémentations font ce qu'on s'y attend.

--
James Kanze GABI Software
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
Fabien LE LEZ
On 21 Jun 2004 01:43:08 -0700, wrote:

(Et en passant -- j'ai bricolé un peu dans ma configuration. Est-ce que
les accents passent correctement de nouveau ?)


Yep :-)


--
;-)
FLL, Epagneul Breton

Avatar
Fabien LE LEZ
[Note : je n'ai pas suivi le thread de très près ; du coup je réponds
au message de James en faisant abstraction du reste du thread -- en
espérant ne pas répondre trop à côté de la plaque ;-) ]

On 21 Jun 2004 01:43:08 -0700, wrote:

Alors, pour une fonction pour trouver le maximum, est-ce que tu penses
que quelque chose du genre :
[...]
ferait l'affaire ?


Perso, je préférerais un code qui sépare deux cas :

- Si begin!=end :

T result= *begin;
++ begin;

while ( begin != end )
{
if ( *begin > result )
{
result = *begin ;
}
++ begin ;
}
return result ;

- Si begin == end (i.e. la liste est vide) : la notion de maximum n'a
pas vraiment de sens ; la fonction peut bien faire ce qu'on veut --
renvoyer le minimum absolu, lancer une exception, renvoyer une valeur
indéfinie, etc. Je préfère séparer explicitement ce cas-là, d'une part
pour expliciter le comportement de la fonction dans ce cas dégénéré,
d'autre part pour pouvoir le modifier facilement sans avoir à modifier
le traitement du cas général.



--
;-)
FLL, Epagneul Breton

Avatar
Vincent Lascaux
| > | Donc l'idée de prendre -std::numeric_limits<double>::max() pour
| représenter
| > | une valeur infinie plus petite que toute autre valeur n'est pas une
idée

| > | applicable à tous les types.
| >
| > Cela me paraît évident puisque « double » n'est pas « tous les
types ».

|
| Je vois pas en quoi c'est évident...

Est-ce que « double » est « tous les types ? La réponse est non.
C'est pas évident ?


Est ce que j'ai dit que double était tous les types ? La réponse est non.
C'est pas évident ?

--
Vincent

Avatar
kanze
Fabien LE LEZ wrote in message
news:...

[Note : je n'ai pas suivi le thread de très près ; du coup je réponds
au message de James en faisant abstraction du reste du thread -- en
espérant ne pas répondre trop à côté de la plaque ;-) ]


T'en fais pas. Moi-même, je répondais à un posting précis, sans avoir
vraiment suivi tout le thread.

On 21 Jun 2004 01:43:08 -0700, wrote:

Alors, pour une fonction pour trouver le maximum, est-ce que tu penses
que quelque chose du genre :
[...]
ferait l'affaire ?


Perso, je préférerais un code qui sépare deux cas :

- Si begin!=end :

T result= *begin;
++ begin;

while ( begin != end )
{
if ( *begin > result )
{
result = *begin ;
}
++ begin ;
}
return result ;

- Si begin == end (i.e. la liste est vide) : la notion de maximum n'a
pas vraiment de sens ; la fonction peut bien faire ce qu'on veut --
renvoyer le minimum absolu, lancer une exception, renvoyer une valeur
indéfinie, etc. Je préfère séparer explicitement ce cas-là, d'une part
pour expliciter le comportement de la fonction dans ce cas dégénéré,
d'autre part pour pouvoir le modifier facilement sans avoir à modifier
le traitement du cas général.


Tout à fait. C'est comme ça que je l'écris en général moi-même. Ce qui
m'intéressait dans mon exemple, ce n'était pas l'algorithme à choisir
pour trouver la maximum, c'était plutôt comment il faut s'attaquer pour
trouver la valeur la plus petite avec std::numeric_limits.

--
James Kanze GABI Software
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
Vincent Lascaux
Relis ce que tu as cité comme message.



l'idée de prendre -std::numeric_limits<double>::max() pour représenter
une valeur infinie plus petite que toute autre valeur n'est pas une idée
applicable à tous les types


Je maintiens que j'ai parlé d'appliquer une *idée* à un autre type. Je
maintiens aussi qu'appliquer une idée implique quelque part adapter l'idée
(mais apparemment l'adaptation c'est pas trop ton truc).

--
Vincent


Avatar
Vincent Lascaux
| >l'idée de prendre -std::numeric_limits<double>::max() pour représenter
| >une valeur infinie plus petite que toute autre valeur n'est pas une
idée

| >applicable à tous les types
|
| Je maintiens que j'ai parlé d'appliquer une *idée* à un autre type. Je
| maintiens aussi qu'appliquer une idée implique quelque part adapter
l'idée


mais quelle idée ? Toutes celles que tu as exposées sont foireuses.


Je pense que tu te trompes de personne, j'ai pas exposé d'idée...
Je disais qu'utiliser l'opposé du champ max de std::numeric_limits pour
représenter une valeur plus petite que toutes les autres (ce qui avait été
fait pour double) n'est pas une bonne idée puisqu'elle n'est pas applicable
à tous les types.

--
Vincent

1 2 3 4