IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

un problème d'entiers


Sujet :

Langage PHP

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 16
    Points : 12
    Points
    12
    Par défaut un problème d'entiers
    bonjour à tous

    Je voudrais simplement retourner un nombre à 2 décimales multiplié par un million, dans un format integer (ie pas de 2.9E+06 ou autre), et j'ai des phénomènes plus qu'étranges.

    Ce qui est bizarre c'est que ça n'arrive que sur certaines valeurs, par exemple '2.09' : c'est ok avec 1.09 et 3.09, 2.19, 2.091 et 2.089, etc...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $cpc = '2.09';
     
    echo $cpc * 1000000; // retourne la valeur correcte : 2090000
    echo "<br/>";
    echo (int)($cpc * 1000000); // retourne 2089999 !!
    echo "<br/>";
    echo (int)($cpc * 1000 * 1000); // retourne la valeur correcte.
     
    $cpc = '1.2';
    echo"<br/>";
    echo $cpc * 1000000; // retourne 1.2E+6
    echo "<br/>";
    echo (int)($cpc * 1000000); // retourne la valeur correcte : 1200000
    echo "<br/>";
    echo (int)($cpc * 1000 * 1000); // retourne la valeur correcte
    J'aurais donc tendance à dire d'utiliser le (int)($cpc*1000*1000) mais j'ai eu d'autres cas où ça ne fonctionnait pas... Est-il donc impossible en php de multiplier un nombre par un million ?? C'est incroyable, ce truc...
    J'ai soumis ça en bug à PHP mais on m'a répondu que c'était un problème de précision, ce que j'ai du mal à croire vu le script.

    Et j'ai l'impression (98% sûr) que ça n'arrivait pas avant de passer en v5.2 de PHP, je pense qu'en 5.0 ça fonctionnait correctement.

    Merci !
    Laurent

  2. #2
    Membre actif
    Inscrit en
    Janvier 2004
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 242
    Points : 271
    Points
    271
    Par défaut
    En gérant ça en mode chaine de caractére peut etre ?

    Faire un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    function mult1million($nb){
     
            $nb=(string)$nb;
    	if(preg_match('@.@',$nb)){
     
    		$tmp=explode('.',$nb);
     
    		$virg=$tmp[1];
     
    		for($i=strlen($tmp[1]);$i<6;$i++){
     
    				$virg.='0';
     
    		}
     
    		return $tmp[0].$virg;
     
    	}else{
     
    		for($i=0;$i<6;$i++){
     
    				$nb.='0';
     
    		}
     
    		return $nb;
     
    	}
     
    }
    $cpc="2.09"
     
    echo mult1million($cpc);

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 16
    Points : 12
    Points
    12
    Par défaut
    en fait c'est ce que je fais comme contournement à l'heure actuelle, je multiplie par 1000 et je concatène '000'.
    C'est quand même un truc de fou

  4. #4
    Membre actif
    Inscrit en
    Janvier 2004
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 242
    Points : 271
    Points
    271
    Par défaut
    Citation Envoyé par lolo92 Voir le message
    en fait c'est ce que je fais comme contournement à l'heure actuelle, je multiplie par 1000 et je concatène '000'.
    C'est quand même un truc de fou
    C'est une limitation d'u a l'arrondi en 32bits non ?

    Faudrait essayer sur un php compilé en 64bits pour voir.

  5. #5
    Membre expert
    Inscrit en
    Janvier 2005
    Messages
    2 291
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 291
    Points : 3 212
    Points
    3 212
    Par défaut
    Citation Envoyé par chaced Voir le message
    C'est une limitation d'u a l'arrondi en 32bits non ?

    Faudrait essayer sur un php compilé en 64bits pour voir.
    Non, la valeur maximale d'un entier sur 32 bits et plutot vers les milliards (quand tu es en entier signé). Cf la doc:
    La taille des entiers dépend de la plate-forme de support, mais la valeur maximale est généralement de 2 milliards et des poussières (c'est un entier signé de 32 bits). PHP ne supporte pas les entiers non signés. La taille des entiers peut être déterminée depuis PHP_INT_SIZE, et la valeur maximale avec PHP_INT_MAX depuis PHP 4.4.0 et PHP 5.0.5.

  6. #6
    Membre actif
    Inscrit en
    Janvier 2004
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 242
    Points : 271
    Points
    271
    Par défaut
    Citation Envoyé par koopajah Voir le message
    Non, la valeur maximale d'un entier sur 32 bits et plutot vers les milliards (quand tu es en entier signé). Cf la doc:
    Sauf que 2.09*1000000 c'est un float signé

  7. #7
    Membre expert
    Inscrit en
    Janvier 2005
    Messages
    2 291
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 291
    Points : 3 212
    Points
    3 212
    Par défaut
    Citation Envoyé par chaced Voir le message
    Sauf que 2.09*1000000 c'est un float signé
    C'est vrai, maintenant un float/double est dans la majorité des cas compris entre des valeurs bien plus grandes (en valeur absolue) que les entiers. Si tu lis la documentation il est dit:
    La taille des nombres décimaux dépend de la plate-forme. Un maximum de ~1.8e308 avec une précision de 14 décimales est une configuration répandue : c'est le format 64 bits IEEE.
    Dans la documentation une fois de plus il est dit a propos de la conversion en entier
    Depuis un nombre à virgule flottante

    Lors de conversion entre un nombre décimal et un entier, le nombre sera arrondi à la valeur inférieure s'il est positif, et supérieure s'il est négatif (conversion dite 'vers zéro').
    Mais ca n'explique pas précisément pourquoi certains nombres et pas d'autres. Dans tous les cas il est dit clairement de ne pas faire confiance à ce genre de conversions.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 012
    Points : 1 093
    Points
    1 093
    Par défaut
    Citation Envoyé par koopajah Voir le message
    Mais ca n'explique pas précisément pourquoi certains nombres et pas d'autres. Dans tous les cas il est dit clairement de ne pas faire confiance à ce genre de conversions.
    Cela dépend comment sont les chiffres sous format binaire :
    2.09 est sans doute égal à 2.08999999, alors que 1.2 est peut-être égal à 1.2000001

    Le solution est la fonction round :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo round($cpc * 1000000);

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 16
    Points : 12
    Points
    12
    Par défaut
    merci, mais encore une fois cela fonctionne pour un et pas pour l'autre...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $cpc = '2.09';
    echo round($cpc * 1000000); //retourne 2090000
     
    $cpc = '1.2';
    echo round($cpc * 1000000); //retourne 1.2E+6

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 012
    Points : 1 093
    Points
    1 093
    Par défaut
    et en utilisant la fonction number_format dans ton echo ?
    peut-être que tu ne devras même plus utiliser la fonction round

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 16
    Points : 12
    Points
    12
    Par défaut
    je n'ai pas essayé avec number_format mais vu que ce sont des entiers je vois mal comment cela pourrait éviter un 2089999 au lieu de 2090000... Et en tout était de cause, cela m'apparait comme étant une solution de bricolage (bricolage que je dois de toute façon faire pour m'en sortir, en concaténant la string '000' au résultat * 1000).

    je ne me sers pas de la fonction round(), c'était pour répondre à ta suggestion précédente...

    merci de ton aide en tout cas

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 012
    Points : 1 093
    Points
    1 093
    Par défaut
    Oui et non

    Avec la fonction round, tu obtiens bien 2090000.

    Autre problème c'est l'affichage de 1.2E+6 au lieu de 1200000. Ces deux chiffres sont exactement identiques. Ce n'est donc plus un problème de précision mais d'affichage. D'où l'intérêt de number_format qui doit te permettre de forcer l'affichage, sans modifier la valeur

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 16
    Points : 12
    Points
    12
    Par défaut
    absolument

    mais mon but était d'arriver au "bon" résultat, ie correct au niveau comptable et au niveau formatage d'affichage.
    ca semble quand même insensé qu'il faille passer par des feintes comme rajouter 000 à la fin du string ou de faire un round et un number_format pour arriver à multiplier un nombre par un million ! même visual basic doit savoir le faire

    enfin bon, je me contente de la solution .'000', la tienne étant également fonctionnelle.

    merci de l'aide de tous !

  14. #14
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 10
    Points : 6
    Points
    6
    Par défaut
    Bonsoir à tous,

    Je suis sur une machine tournant sous Windows 7 64 bits. Seulement, quand j'affiche la valeur de PHP_INT_MAX, j'ai la valeur 2147483647 (soit celle d'une machine sous 32 bits).

    J'ai téléchargé la dernière version de wamp et d'easyphp, en pensant que ça venait de là, mais toutes les 2 sont sensées être compatibles avec cet OS sur 64 bits...

    Quelqu'un aurait-t-il une idée sur la raison de cette limite ?

    Cordialement,

    Olivier.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2003] Problème affichage entiers
    Par Fabiani dans le forum Excel
    Réponses: 2
    Dernier message: 23/06/2009, 22h42
  2. Problème entre entiers et réels
    Par Caroline_1 dans le forum Fortran
    Réponses: 5
    Dernier message: 08/03/2009, 13h02
  3. Problème cast entier/réel
    Par darkwall_37 dans le forum Débuter
    Réponses: 2
    Dernier message: 15/06/2008, 00h15
  4. Problème Class Entier
    Par stansoad0108 dans le forum Général Java
    Réponses: 4
    Dernier message: 03/01/2008, 19h00
  5. problème d'entier
    Par boucher_emilie dans le forum ASP
    Réponses: 7
    Dernier message: 13/07/2004, 16h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo