• # :)

    Posté par  (site web personnel) . Évalué à 3.

    bienvenu dans le monde des arrondis numérique
  • # Histoire de codage

    Posté par  . Évalué à 1.

    Je pense que tu viens de découvrir que les flottants ne sont généralement pas codés de manière exacte dans la machine. :) Ceci combiné à une troncature et on a ce que tu observes. Enfin, je peux me tromper, c'est juste une explication possible.
  • # 100.00

    Posté par  (site web personnel) . Évalué à 1.

    Essaye de mutiplier par 100.00 c'est peut etre un probleme du au typage dynamique.
    • [^] # Re: 100.00

      Posté par  (site web personnel, Mastodon) . Évalué à 1.

      Bonne idée, mais non: (
      http://www.lzi.ch/plop.php(...) http://www.lzi.ch/plop.phps(...)

      Et même avec 15.90, c'est ok. Qu'est-ce que le type qui a écrit ça a contre 1990?? :*)

      La gelée de coings est une chose à ne pas avaler de travers.

      • [^] # Re: 100.00

        Posté par  . Évalué à 1.

        J'ai voulu tester la même chose dans Scilab (Version : 3.1.1)
        Voila ce que l'on obtient :

        -->a=19.90
        a =
        19.9
        -->a*100
        ans =
        1990.
        -->int(a*100)
        ans =
        1989.

        -->a2=15.9
        a2 =
        15.9
        -->int(a2*100)
        ans =
        1590.

        -->b=a*100
        b =
        1990.
        -->int(b)
        ans =
        1989.
        -->int(1990)
        ans =
        1990.
        -->round(b)
        ans =
        1990.

        round(x) : arrondit les éléments de x aux entiers les plus proches.
        int(X) : renvoie une matrice d'entiers dont les éléments sont les arrondis vers zéro des éléments de x.


        -->int(b*10000)
        ans =
        19899999.
        -->int(b*10000000)
        ans =
        1.990D+10


        Voila ce qu'il en est dans Scilab : pareil en clair
        • [^] # Re: 100.00

          Posté par  (site web personnel, Mastodon) . Évalué à 1.

          Et en python:

          Python 2.3.5 (#2, Jun 19 2005, 13:28:00)
          >>> 19.90 * 100
          1989.9999999999998
          >>> 15.90 * 100
          1590.0

          ça m'scie l'caramel :-/

          La gelée de coings est une chose à ne pas avaler de travers.

          • [^] # Re: 100.00

            Posté par  . Évalué à 3.

            ruby...

            irb(main):001:0> 15.90 * 100
            => 1590.0
            irb(main):002:0> 19.90 * 100
            => 1990.0

            change de caramel ça ira mieux ;-)
          • [^] # Re: 100.00

            Posté par  (site web personnel) . Évalué à 1.

            mais :
            >>> print 19.90 * 100
            1990.0

            :)
  • # BCMath

    Posté par  (site web personnel) . Évalué à 1.

    BCMath est la pour régler ce genre de problème...
    http://fr.php.net/manual/fr/ref.bc.php(...)
  • # explication

    Posté par  . Évalué à 1.

    Tiens j'ai vu ça quelque part il y a pas longtemps :

    http://blog.leetsoft.com/articles/2005/09/27/wtf(...)


    Casting a float to an integer means you lose all the information after the decimal. Rounding should not occur in this case.
  • # Tout à fait

    Posté par  . Évalué à 2.

    Normal, c'est du au fait que les nombre en virgule flottante ne sont pas précis en php.

    Pour contourner ce problème, si on a besoin de précision (et donc éviter les problèmes d'arrondi) il faut utiliser http://lu.php.net/manual/fr/ref.bc.php(...) Binary Calculator.

    Maintenant à toi de voir si ton projet a vraiment besoin de cette précision ou si l'arrondi est acceptable
  • # Codage des floats

    Posté par  . Évalué à 4.

    Un entier, c'est codé en binaire
    0b => 0d
    1b=> 1d
    10b => 2d
    etc....
    et un nombre se décompose sur les puissances de 2
    18 = 0*1 + 1*2^1 + 0*2^2 + 0*2^3 + 1*2^4 = 10010b


    Quand tu code un flottant, la partie après la virgule est aussi codée en binaire en décomposant par puissance négative de 2
    a*1/2^1 + b*1/2^2 +c*1/2^3 + ... + x*1/2^n

    Un nombre comme 1/3 a un nombre de virgule infini. Donc on ne pourra jamais trouver un "décomposition en série de 1/2^n" finie égale à 1/3. Un float est stocké sur un nombre fini de bits et donc s'approchera plus ou moins bien de ton 1/3 mais n'y arrivera jamais exactement.

    Conclusion quand tu réaffiche ton nombre, il affiche la valeur stockée.
    Ex : 0.8126 si on a que 4bits de précisions
    0.826 = 1/2 + 1/4 + 0/8 +1/16 (+1/10000)

    La partie 1/10000 n'est pas codable avec notre système, quand on réaffichera notre nombre stocké, on aura 0.825 et non 0.826
    • [^] # Re: Codage des floats

      Posté par  . Évalué à 1.

      Effectivement, je suis OK avec toi, si je prend notre exemple si dessus on obtient donc :
      19.90d = 19d + 0.90d
      19d = 16 + 2 + 1 = 10011b
      0.90d = 1/2 + 1/4 + 1/8 + 1/64 + 1/128 + 1/1024 + 1/2048 ...
      = 1/2^1 + 1/2^2 + 1/2^3 + 1/2^6 + 1/2^7 + 1/2^10 + 1/2^11 + 1/2^14 + 1/2^15 + etc . etc.
      = 111001100110011...

      Donc comme dans ton exemple 0.90 n'est pas codable.

      Maintenant, j'ai une question : qu'est-ce qui rend 15.90d codable et 19.90 non codable ? Parce si on regarde bien, seul 19.90 pose problème ci-dessus.


      J'au eu beau chercher dans Wikipedia, Google, rien de probant
      • [^] # Re: Codage des floats

        Posté par  (site web personnel) . Évalué à 4.

        Ca tient là aussi à la manière dont on stoque les flottants.

        Ce que tu fais c'est retrancher la partie entière et remarquer que la partie décimale est identique. Et là tu te dis que la précision devrait être la même.

        Ton erreur c'est que le soft ne sépare pas la partie entière et la partie décimale. Lui sépare un nombre et une puissance : X * 10^Y, il stocke X et Y.
        Bref, ce n'est pas 15 + 0.90 et 19 + 0.90 qu'il faut comparer mais 0.1590 * 10^2 et 0.1990 * 10^2. La bonne question c'est donc : 0.1590 et 0.1990 sont exprimables en puissance de deux ?


        Note : je parle de mémoire de mes anciens cours, je peux me tromper sur les détails, mais le principe est là. Tu ne peux pas te contenter de dire que vu que la partie décimale est la même si l'un est stockable l'autre l'est.
      • [^] # Re: Codage des floats

        Posté par  . Évalué à 2.

        2 choix principaux : Soit un nombre est codable avec exactitude soit il ne l'est pas. Dans le cas ou il ne n'est pas deux choix : soit le nombre qui est stoqué (le plus proche possible donc) est plus petit que celui au quel on s'attends soit il est plus grand...

        Ce qui en tout fait 3 cas, dont un ne donne pas ce à qui on s'attends quant on cast en int, la conclusion est simple : faire un cast d'un nombre IEEE-754 vers un int c'est chercher les emmerdes.
  • # moi aussi

    Posté par  (site web personnel) . Évalué à 2.

    J'ai moi aussi un bug du à PHP.
    j'ai fait un script pour la notation scientifique (cours de seconde math/physique)

    http://kobold.myftp.org/math/ecriture_science.php(...)

    Le script génère un nombre aléatoire.
    genre 0,015668
    et il faut que l'élève trouve que ça fait 1,5668 .10^"-2"

    donc bref je compare deux nombres.
    celuidonné par l'élève : 1,5668
    et celui donnée par le script : 1,5668

    et de temps en temps le script affiche faux alors que ce sont les mêmes nombres.

    J'ai fait afficher les deux nombres par la page, il s'agit bien des deux nombres ci dessus.
    mais quand je fais leur différence : j'observe une différence d'environ 1E-16

    Conclusion j'ai modifié mon script pour qu'il donne juste aux élèves si la différence entre les deux nombres est inférieur à 1E-15 (mais mathématiquement ça me gêne !)

    Si ça intéresse, je peux fournir le script à qui veut !
    • [^] # Re: moi aussi

      Posté par  (site web personnel) . Évalué à -1.

      Au passage, quelqu'un saurait-il comment forcer PHP à afficher les nombres en écriture décimale.
      parce que 0,00001 est écrit par PHP sous forme 1E-5 et que ça ne m'intéresse pas du tout dans le cas de mon script.

      (je pose la question ici, vu que les forums me sont interdits faute de suffisament d'XP)
  • # ha les joies des virgules flottantes

    Posté par  . Évalué à 1.

    On a le meme genre de problème avec tout les langages (ca serait pas un pattern récurrent ca d'ailleur?)
    En java, un System.out.println(19.90*100) donnerait le meme genre d'erreur, c'est pour cela qu'il faut systématiquement un formateur (NumberFormat en l'occurence).

    En PHP, on peut s'en sortir avec un printf :

    echo (int)(sprintf("%F", 19.90*100));

    Mais ca me semble un peu gruick quand meme.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.