7763 sujets

Développement web côté serveur, CMS

Hello

Merci à vous de prendre du temps pour m'aider Smiley smile

Je suis face à un problème curieux. Je dois faire une boucle for avec la valeur de $i incrémenté de 0.5 par itération.
et par itération, je dois tester si $i est un nombre à virgule ou un entier, donc j'utilise is_float() natif à PHP.

Le problème c'est que à la première itération mon $i est un int (tester avec var_dump), à la deuxième (+0.5) il devient un float (normal !), et ensuite à la troisième ainsi que toutes les autres il reste un "float".... donc je comprend pas pourquoi, est ce à cause du +0.5 ?

Peut être que int + float = float peut importe si le résultat est un entier.

Voici mon code, simple :

$b = 0;
for ($i=0; $i < 5; $i+=0.5) { 
            if(is_float($i))
            {
                $b += 1;
            }
            var_dump($i);
            var_dump(is_float($i));
}


Dans ce code, $b devrait potentiellement être incrémenter 5 fois le if est "true" à chaque itération...
les var_dump affichent bien float pour les 9 dernières itérations.
Modifié par JENCAL (11 Jul 2018 - 12:45)
Bonjour,
C'est en effet assez étonnant.
Je pense que tu peux t'en sortir en faisant cette comparaison:
if(!(int)$i == $i)


C'est à dire en comparant la valeur entière de $i à $i.
Normal. Si tu utilises un nombre en virgule flottante, le résultat est en virgule flottante et gardera ce type jusqu'au bout.

Il te faut multiplier la borne de $i et son incrément par 2 et utiliser l'opérateur % :
<?php
$b=0;
for($i=0, $iMax=10; $i<$iMax; $i++) {
    echo "i: $i ".gettype($i)."\n";
    if($i % 2 == 0) { $b++; echo "b : $b\n"; }
 }
?>

Résultat :
i: 0 integer
b : 1
i: 1 integer
i: 2 integer
b : 2
i: 3 integer
i: 4 integer
b : 3
i: 5 integer
i: 6 integer
b : 4
i: 7 integer
i: 8 integer
b : 5
i: 9 integer

Modifié par bazooka07 (11 Jul 2018 - 14:07)
bazooka07 a écrit :
Normal. Si tu utilises un nombre en virgule flottante, le résultat est en virgule flottante et gardera ce type jusqu'au bout.

Il te faut multiplier la borne de $i et son incrément par 2 et utiliser l'opérateur % :


Ok je savais pas qu'il gardait son type jusqu'au bout. Gros problème pour moi du coup.

Par contre j'ai pas compris le fais de multiplier $i et son incrément par 2 car dans le résultat je n'ai que des entiers, alors que je cherche à avoir les deux, entier ET nombre à virgule.

Je dois avoir 0 - 0.5 - 1 - 1.5 - 2 - 2.5 etc... etc.. car je dois afficher des "notes" sous forme d'étoile et en gros je génère cet autre portion code
https://codepen.io/JUSEN/pen/bjdVYG?editors=1100
ce code fera partie d'un <td> d'une <table> généré en PHP. d'ou la boucle pour savoir si la note est comprise entre 0 et 5. En sachant que toutes les infos généré dans le HTML du codepen (tous les attributs) sont généré également coté PHP, les ids, classe, name, for, etc...
Le plus simple serait de "caster" le tout en string, et de faire des explodes sur mon $i et de tester la taille du résultat pour savoir si c'est un nombre à virgule ou pas.

$b = 0;
for ($i=0; $i < 5; $i+=0.5) {
        $b = (string)$i;
        $c = explode(".",$b);
        if(count($c) > 1)
        {
            var_dump($i);
        }
}


Voila, avec ce petit code je peux cibler mes itérations correspondantes à un nombre à virgule!
Rien ne t'empêche de calculer une nouvelle variable à partir du compter $i :
<?php
$b=0;
for($i=0, $iMax=10; $i<$iMax; $i++) {
    $k = $i / 2;
    echo "k : $k ".gettype($k)."\n";
    if($i % 2 == 0) { $b++; echo "b : $b\n"; }
 }
?>

C'est plus élégant que faire du cast et de l'explode.
En vitesse d'execution, cela me semble plus rapide.
Meilleure solution
bazooka07 a écrit :
Rien ne t'empêche de calculer une nouvelle variable à partir du compter $i :
&lt;?php
$b=0;
for($i=0, $iMax=10; $i&lt;$iMax; $i++) {
    $k = $i / 2;
    echo "k : $k ".gettype($k)."\n";
    if($i % 2 == 0) { $b++; echo "b : $b\n"; }
 }
?&gt;

C'est plus élégant que faire du cast et de l'explode.
En vitesse d'execution, cela me semble plus rapide.


Ahh, la on se rapproche grandement de ce que je recherche, je te remercie pour cela!
Je vais tester cette approche qui me parait pas mal du tout.
Bonjour,
Je me répète, mais ceci fonctionne:
$b = 0;
for ($i=0; $i < 5; $i+=0.5) { 
           if(!(int)$i == $i)
            {
                $b += 1;
            }
}
loicbcn a écrit :
Bonjour,
Je me répète, mais ceci fonctionne:
$b = 0;
for ($i=0; $i &lt; 5; $i+=0.5) { 
           if(!(int)$i == $i)
            {
                $b += 1;
            }
}


Pardon, je ne t'ai pas répondu plus tot..

Dans ton cas b est toujours égale à 1.
Moi je chercher à l'incrémenté uniquement si le $i est un nombre à virgule.
là ton test c'est "Si $i est un int" et il l'ai UNIQUEMENT lors de la première itération. Du coup pour le moment je garde la solution de bazooka
Modifié par JENCAL (12 Jul 2018 - 14:30)
Bonjour,

Il manquait une parenthèse autour de la condition, ou en bougeant le "!", cela donne:
<?php
$b = 0;
for ($i=0; $i < 5; $i+=0.5) { 
           if((int)$i != $i){
                $b++; 
            }
            var_dump('$i='. $i, '$b='. $b);
}

ce qui donne :
$i=0 ---- $b=0
$i=0.5 ---- $b=1
$i=1 ---- $b=1
$i=1.5 ---- $b=2
$i=2 ---- $b=2
$i=2.5 ---- $b=3
$i=3 ---- $b=3
$i=3.5 ---- $b=4
$i=4 ---- $b=4
$i=4.5 ---- $b=5

Voilà.
Modifié par loicbcn (16 Jul 2018 - 08:55)