Partage
  • Partager sur Facebook
  • Partager sur Twitter

Plus pletit float positif

Sujet résolu
    13 juin 2021 à 18:16:53

    Bonjour. J'effectue une comparaison entre deux float. Pour certaines raisons algorithmiques, c'est le test a<b qui m'intéresse, mais je dois utiliser <= et pas <. Il faut donc que j'effectue un test du type a+epsilon <= b. Mon algorithme sera d'autant plus rapide que epsilon est petit. J'aimerai donc entrer le plus petit flottant >0. L'idéal serait une constante du style INT_MAX, mais appelée FLOAT_MIN_POSITIF. Cependant, je ne trouve pas une telle constante.

    Ps: Avec cette valeur de epsilon, a-t-on  bien toujours a+epsilon != a ?

    -
    Edité par BelhouariSéhane 13 juin 2021 à 18:26:02

    • Partager sur Facebook
    • Partager sur Twitter
    Le basheur
      13 juin 2021 à 18:35:25

      cppreference.com est ton ami: https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon

      Pour a+epsilon != a, je ne pense pas que cela soit le cas avec de grand nombre (à vérifier), mais de toute façon, l'epsilon sur les grands nombre s n'a probablement pas de sens.

      • Partager sur Facebook
      • Partager sur Twitter
        13 juin 2021 à 18:40:43

        Salut,

        Si tu inclus le fichier <limits>, tu peux disposer de std::numeric_limits<float>::epslion qui fait le taf ;)

        • Partager sur Facebook
        • Partager sur Twitter
        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
          13 juin 2021 à 19:54:36

          Salut,

          En plus de cela, si tu n'as pas de nombres réels à gérer, tu peux peut-être t'en tirer bien en utilisant des rationnels. :)

          • Partager sur Facebook
          • Partager sur Twitter
          Tutoriel Ruby - Bon tutoriel C - Tutoriel SDL 2 - Python avancé - Faîtes un zeste, devenez des zesteurs
            13 juin 2021 à 21:52:40

            Merci pour le lien. Le epsilon ne modifie par addition que les float <0.01 (à la louche). Donc multiplier par 1.f + 100.f * epsilon permet de trouver un successeur très proche d'un flottant, même de grande taille.
            • Partager sur Facebook
            • Partager sur Twitter
            Le basheur
              14 juin 2021 à 0:19:54

              BelhouariSéhane a écrit:

              Merci pour le lien. Le epsilon ne modifie par addition que les float <0.01 (à la louche). Donc multiplier par 1.f + 100.f * epsilon permet de trouver un successeur très proche d'un flottant, même de grande taille.

              Non, non, je peux t'assurer que, sur un float,epsilon va modifier les valeurs avec un précision bien supérieure à 0.01...

              Si tu regarde la sortie du code donné en exemple dans le lien, tu remarquera que la précision pour  les double est de l'ordre de 17 chiffres après la virgule.

              Autant dire que celle d'un float doit très certainement tourner aux alentours de 9 ou 10 chiffres après la virgule (à la louche) ;)

              Si tu as eu une impression différente au travers tes essais, je serais près à parier que c'est qu'elle est due à la précision lors de l'affichage des données (un std::set_precision(12) placé dans le flux avant l'affichage pourrait changer énormément :D)

              Et, si ce n'est effectivement pas à cause de la précision lors de l'affichage, il sera sans doute intéressant d'observer les valeurs que tu souhaites représenter avec tes float.

              En effet, les types float et double (et long double, que j'ai failli oublier) sont des types dit à "virgule flottantes".  C'est à dire qu'ils représentent leur valeur (pour faire simple) sous une forme "scientifique".

              C'est à dire que ces types utilisent ce que l'on appelle une "mantisse" pour représenter une valeur "au plus proche", mais dont on va partir du principe qu'il n'y a qu'un seul chiffre avant la virgule et d'un exposant qui indique le nombre de chiffres dont il faut décaler la virgule vers la droite ou vers la gauche, un peu comme le nombre d'avogadro qui est représenté sous la forme de 6.022 140 76 * 1023.

              Il va donc de soi que plus le nombre de chiffres nécessaire à la représentation de la valeur entière sera important, plus le nombre de chiffre "restant" après la virgule (et donc la précision) sera faible.  Mais ca, c'est le "triste lot" de tout système fini : on ne peut pas représenter plus de valeurs que ce que le système nous permet au travers d'un type donné :p

              Et c'est d'autant plus vrai qu'il faut avoir recours à une conversion pour permettre à l'homme et à la machine de se mettre d'accord sur une valeur donnée (et, surtout, pour être sur qu'ils considéreront tous les deux que la valeur qu'on leur fourni est "correcte" :$ )

              Ceci étant dit, si le float ne t'apporte décidément pas (après vérifications de ta part) la précision attendue, peut-etre que les double , voir les long doubles pourront d'avantage te convenir ;)

              Et, au pire, tu peux aussi te tourner vers des bibliothèques tierces spécialisées dans la représentation de valeurs réelles telles que mpfr (ou, pourquoi pas, comme suggéré par yo@, vers l'utilisation de rationnels).

              Par contre, ces alternatives te demanderont sans doute bien plus de travail pour obtenir le résultat que tu recherche :p

              • Partager sur Facebook
              • Partager sur Twitter
              Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                14 juin 2021 à 11:50:36

                BelhouariSéhane a écrit:

                Merci pour le lien. Le epsilon ne modifie par addition que les float <0.01 (à la louche). Donc multiplier par 1.f + 100.f * epsilon permet de trouver un successeur très proche d'un flottant, même de grande taille.


                Non, ça dépend du premier chiffre significatif. Virgule flottante je rappelle.

                Il faut penser comme un physicien :

                - quand tu mesures un atome, tu as besoin d'être à 10^-10 mètres près.

                - quand tu mesures la distance entre des planètes, tu n'es pas a 1000 km près...

                • Partager sur Facebook
                • Partager sur Twitter

                Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                  1 juillet 2021 à 18:20:35

                  Merci. Je vois bien ce que vous dites. Cependant, je préfère ne pas a avoir à trouver l'ordre de grandeur avant d'ajouter epsilon (c'est une source de disfonctionnement de plus si je décide de modifier ces ordres). Je n'avais pas pensé à ce que le 0.01 soit dû à l'affichage. 

                  Multiplier par 1.f+epsilon reste donc le plus simple à mon goût.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Le basheur

                  Plus pletit float positif

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown