Problème avec round()

Eléphant du PHP | 153 Messages

23 avr. 2009, 10:18

Bonjour à tous,

J'ai un soucis avec round().
J'utilise :
// où $amount = '1.204';
// et $sql_select['tHT'] = '0.931';

$total_ht = round($amount + $sql_select['tHT'], 2);

// donc :
// $total_ht = '2.135';
// avec round() $total_ht devrait être = '2.14';
Dans ma table, le champ total_ht = double; 16,2
Mais cela m'insère '2.13' au lieu de '2.14'

Je ne vois pas d'où peut provenir le problème.
Merci pour votre aide :wink:

D4Y
Eléphant du PHP | 52 Messages

23 avr. 2009, 11:04

C'est normal que tu sois à 2.13 car pour etre au supérieur tu devrais avoir 2.136 et non 2.135 !

<?php
function ceiling($value, $precision = 0) {
return ceil($value * pow(10, $precision)) / pow(10, $precision);
}
?>
Modifié en dernier par D4Y le 23 avr. 2009, 11:14, modifié 1 fois.

Eléphant du PHP | 153 Messages

23 avr. 2009, 11:09

C'est normal que tu sois à 2.13 car pour etre au supérieur tu devrais avoir 2.136 et non 2.135 !
Non, je ne crois pas, avec '2.135' on devrait bien passer à '2.14', arrondi supérieur à partir de 5.

Pris sur phpmanuel :
echo round(5.045, 2);    // 5.05

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 avr. 2009, 11:16

C'est un bug sans en être un... En fait la fonction round() lorsqu'elle est utilisée pour arrondir des nombres qui tombent exactement sur le demi va arrondir les pairs à l'inférieur et les impairs au supérieur.
echo round(1.135, 2);    // 1.14
echo round(2.135, 2);    // 2.13
echo round(3.135, 2);    // 3.14
La raison de ce comportement (pour le moins abérant selon moi) est financier et absolument pas mathématique, afin de ne pas toujours arrondir au supérieur et ainsi prélever un peu plus d'argent, ou perdre un peu plus d'argent à chaque fois que tu vas arrondir. Ca permet d'espérer avoir un compte qui en moyenne devrait avec un peu de chance rester équilibré (et je vous ferais grace de mon avis en la matière).

Ca avait été "corrigé" avec php 4.3, c'est revenu avec php 5.0 ...
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 153 Messages

23 avr. 2009, 11:28

Merci pour vos réponses :wink:

J'ai fait une fonction :
function round2($number, $round = 2)
	{
		$temp_value = $number * pow(10, $round);
		$temp_value = ceil($temp_value);
		$number = $temp_value / pow(10, $round);

		return $number;
	}
L'insertion est bonne dans ma table avec '2.14'
Pensez-vous que je peux utiliser cette fonction sans risque ?

Merci.

EDIT :
Ah ben non, ça ne fonctionne pas non plus avec :
'0.262' c'est arrondi à '0.27' !
J'ai essayé aussi avec la fonction de D4Y, même résultat.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 avr. 2009, 15:11

Une astuce à la c** mais qui fonctionne :
echo round(2.135 + 0.0000001, 2);    // 2.14
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 153 Messages

23 avr. 2009, 15:24

Une astuce à la c** mais qui fonctionne :
echo round(2.135 + 0.0000001, 2);    // 2.14
Il n'y a aucun risque à utiliser ça ? ça fonctionne à 100% ?

Errfffff, va falloir que je modifie l'ensemble du script, suis pas sorti de l'auberge :lol:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 avr. 2009, 15:36

J'avous ne pas avoir essayé plus que ça... j'imagine que ça doit probablement dépendre de ton nombre de décimales et des valeurs de celles-ci, encore que même avec un :
echo round(1.13444444 + 0.0000001, 2);    // 1.13
J'obtiens bien 1.13 en arrondissant...

Quant à modifier l'ensemble du script, suffit juste de changer ta fonction round2() :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 153 Messages

23 avr. 2009, 15:46

J'avous ne pas avoir essayé plus que ça... j'imagine que ça doit probablement dépendre de ton nombre de décimales et des valeurs de celles-ci, encore que même avec un :
echo round(1.13444444 + 0.0000001, 2);    // 1.13
J'obtiens bien 1.13 en arrondissant...

Quant à modifier l'ensemble du script, suffit juste de changer ta fonction round2() :)
Ok, je tente ça.
Quant à modifier ma fonction, euh ... là je suis un peu pommé :oops:

EDIT :
si je fais uniquement ça, c'est bon ?
function round2($number, $round = 2) 
{ 
        $number = ($number + 0.0000001, $round);

        return $number; 
}
Merci.
Modifié en dernier par Cobra52 le 23 avr. 2009, 15:53, modifié 1 fois.

Mammouth du PHP | 991 Messages

23 avr. 2009, 15:50

function round2($number, $round = 2)
    {
        $number = round($number + 0.0000001, $round);

        return $number;
    } 
Surement quelque chose de ce genre ^^
DevOps, Symfony4, Hoa

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

23 avr. 2009, 15:51

Bah basiquement :
function round2($number, $round = 2) { 
        return round($number + 0.0000001, $round); 
}
Maintenant tu dois pouvoir faire un truc un peu plus propre et gérer le nombre de 0 en fonction de $round .... c'était juste histoire de centraliser l'arrondi pour que si jamais tu trouvais mieux, t'ai pas à repasser partout :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 153 Messages

23 avr. 2009, 15:55

Bah basiquement :
function round2($number, $round = 2) { 
        return round($number + 0.0000001, $round); 
}
Maintenant tu dois pouvoir faire un truc un peu plus propre et gérer le nombre de 0 en fonction de $round .... c'était juste histoire de centraliser l'arrondi pour que si jamais tu trouvais mieux, t'ai pas à repasser partout :)
Oups, j'ai posté mon "EDIT" en même temps que vous, et avec une erreur grosse comme moi !

Merci à vous pour votre aide :D
Je me lance avec ça.

Eléphant du PHP | 153 Messages

28 avr. 2009, 14:40

Une dernière question.

Je travaille en local avec Easyphp, php5, mysql5

J'insère, dans ma bdd, des montant de tva à 3 chiffres après la virgule (tels qu'ils sont générés par php), qui semblent respecter les règles d'arrondi.
Est-ce normal ?

Merci à vous.

EDIT : en fait, non, c'est le même problème !