OVH Cloud OVH Cloud

Probleme d'arrondi

18 réponses
Avatar
Laurent Petr
La commande round n'a pas un comportement cohérent sur certains serveur :
round(118.265,2) donne 118.27
et round(215.915,2) donne 215.91

Mais sur un autre serveur j'ai un résultat correct (215.92)...

Comment contourner le problème ?

Laurent

8 réponses

1 2
Avatar
Olivier Miakinen

L'arrondi d'un nombre dont la partie décimale est 0,5 est l'entier pair
le plus proche.
Donc

1,5 arrondi à 2
2,5 arrondi à 2
3,5 arrondi à 4
4,5 arrondi à 4
...

Comportement assuré par les familles Pentium entre autres.


Mettons que l'arrondi puisse avoir plusieurs définitions pour les
moitiés de nombres impairs. Mais je n'ai toujours pas compris pourquoi
tu appelais « plafond » cette définition de l'arrondi parfaitement
valide, quoique différente de celle de la norme IEEE-754.

Avatar
Stephane Santon
Bonjour,

Comportement assuré par les familles Pentium entre autres.


Mettons que l'arrondi puisse avoir plusieurs définitions pour les
moitiés de nombres impairs. Mais je n'ai toujours pas compris pourquoi
tu appelais « plafond » cette définition de l'arrondi parfaitement
valide, quoique différente de celle de la norme IEEE-754.


OK. Le terme de "Plafond" n'est pas bon.
Je voulais dire "Arrondi par excès".

--
** Anti-Spam : ajouter [usenet] dans l'objet pour ne pas être rejeté.

Cordialement, Stéphane *** http://www.team-santonum.com
Loisirs, nature, arts, technologie : accueil en Charente-Maritime


Avatar
Stephane Santon
Bonjour,

L'arrondi d'un nombre dont la partie décimale est 0,5 est l'entier pair
le plus proche.
2,5 arrondi à 2
3,5 arrondi à 4
Comportement assuré par les familles Pentium entre autres.



Tu mélanges vraiment tout.

La norme IEEE-754 définit la représentation binaire de réels. Quand elle
parle d'arrondi, c'est pour le dernier bit de la mantisse lors des
calculs. Cela n'a strictement rien à voir avec ton interprétation
décimale (les ordinateurs n'ont pas 10 doigts pour compter).


As-tu essayé d'arrondir un décimal sur ton pentium ?

http://www.vuibert.com/DOC/200-annexe-h%20(2e%20FR).pdf p15/80 #795

--
** Anti-Spam : ajouter [usenet] dans l'objet pour ne pas être rejeté.

Cordialement, Stéphane *** http://www.team-santonum.com
Loisirs, nature, arts, technologie : accueil en Charente-Maritime


Avatar
jz
Stephane Santon wrote:
Bonjour,


L'arrondi d'un nombre dont la partie décimale est 0,5 est l'entier pair
le plus proche.
2,5 arrondi à 2
3,5 arrondi à 4
Comportement assuré par les familles Pentium entre autres.



Tu mélanges vraiment tout.

La norme IEEE-754 définit la représentation binaire de réels. Quand elle
parle d'arrondi, c'est pour le dernier bit de la mantisse lors des
calculs. Cela n'a strictement rien à voir avec ton interprétation
décimale (les ordinateurs n'ont pas 10 doigts pour compter).



As-tu essayé d'arrondir un décimal sur ton pentium ?


Moi non, mais le processeur le fait à chaque calcul pour limiter les
erreurs. Ne pouvant stocker tous les éléments d'un ensemble infini (R)
dans un nombre fini de bits, il faut bien trouver des compromis,
l'arrondis en est un. Mais il se fait au niveau de la représentation
binaire des flottants, ce qui n'a rien, mais vraiment rien à voir avec
l'écriture décimale avec laquelle nous sommes habitués de les lire.



http://www.vuibert.com/DOC/200-annexe-h%20(2e%20FR).pdf p15/80 #795



C'est un excellent document, et je te félicite de l'avoir déniché.
Maintenant je te conseille de le lire et de m'indiquer les passages où
il me contredirait.

Ton interprétation de la formule que je donne pour arrondir un nombre
comme étant un "plafond" ou un "Arrondi par excès" montre que tu n'as
pas compris la notion de partie entière utilisée dans ce contexte. Fais
les calculs avec des exemples simples pour voir ce qui se passe.

Tiens, je te redonne la formule pour arrondir un réel à 2 décimales (en
base 10) :
$valeurarrondie = ((int)($valeur*100+0.5))/100;

Je te garanti le résultat, tant que $valeur<10e12. Au delà les erreurs
risquent d'être significatives, donc il faut changer de représentation
numérique.

Jacques



Avatar
John Gallet
Bonjour,


Euh... Je crois que la réponse est à côté de la plaque là ...
Rien à voir avec . ou , à mon humble avis.
En effet j'avais lu les exemples en diagonale.



L'heure des messages que vous voyez ici (18:14) n'a rien à voir avec
l'heure affective d'envoi.
Ces messages dates de nombreux jours.
Pas de notre faute si proxad les a gardés au chaud pendant plusieurs

jours. Idem avec news.free.fr.

a++
JG


Avatar
Stephane Santon
Bonjour,

L'arrondi d'un nombre dont la partie décimale est 0,5 est l'entier pair le plus proche.
Tu mélanges vraiment tout. Cela n'a strictement rien à voir avec ton interprétation

décimale (les ordinateurs n'ont pas 10 doigts pour compter).


As-tu essayé d'arrondir un décimal sur ton pentium ?
Moi non, mais le processeur le fait à chaque calcul pour limiter les erreurs.



Le débat que j'ai soulevé n'est pas un arrondi de calcul mais un arrondi
demandé explicitement par "l'utilisateur" en base 10, DEFINI par la
norme.

http://www.vuibert.com/DOC/200-annexe-h%20(2e%20FR).pdf p15/80 #795
C'est un excellent document, et je te félicite de l'avoir déniché.

Maintenant je te conseille de le lire et de m'indiquer les passages où
il me contredirait.


Eh bien voilà : je (re)cite :
<<
1. Quand on arrondit un résultat « à mi-chemin » vers le nombre flottant
le
plus proche, on prend celui qui est pair.

Pour préciser le point (1), il faut noter qu'avec une opération sur deux
nombres
flottants, le résultat est généralement un nombre qui ne peut être
exactement représenté
comme un autre nombre flottant. Par exemple, dans un système flottant
utilisant la base 10 et deux nombres significatifs, 6,1 × 0,5 = 3,05.
Ceci doit être
arrondi à deux chiffres. Doit-on arrondir à 3,0 ou 3,1 ? Dans la norme
IEEE, de
tels cas à mi-chemin sont arrondis vers le nombre dont le chiffre de
poids faible est
pair. Donc, 3,05 est arrondi à 3,0 et non à 3,1.



Tiens, je te redonne la formule pour arrondir un réel à 2 décimales (en
base 10) :
$valeurarrondie = ((int)($valeur*100+0.5))/100;


J'arrondi 3.05 pour l'exemple du document à 1 décimale :

$valeur = 3.05;
$arrondi = ((int)($valeur*10+0.5))/10;
= ((int)( 3.05 *10+0.5))/10;
= ((int)( 30.5 +0.5))/10;
= ((int)( 31 ))/10;
= ( ( 31 ))/10;
= 3.1

CONTRAIREMENT
à ce qui est cité ci-dessus dans le document, qui préconise 3.0 .

--
** Anti-Spam : ajouter [usenet] dans l'objet pour ne pas être rejeté.

Cordialement, Stéphane *** http://www.team-santonum.com
Loisirs, nature, arts, technologie : accueil en Charente-Maritime




Avatar
jz
Stephane Santon wrote:
Bonjour,


Bonjour

...

Eh bien voilà : je (re)cite :
<<
1. Quand on arrondit un résultat « à mi-chemin » vers le nombre flottant
le
plus proche, on prend celui qui est pair.

Pour préciser le point (1), il faut noter qu'avec une opération sur deux
nombres
flottants, le résultat est généralement un nombre qui ne peut être
exactement représenté
comme un autre nombre flottant. Par exemple, dans un système flottant
utilisant la base 10 et deux nombres significatifs, 6,1 × 0,5 = 3,05.
Ceci doit être
arrondi à deux chiffres. Doit-on arrondir à 3,0 ou 3,1 ? Dans la norme
IEEE, de
tels cas à mi-chemin sont arrondis vers le nombre dont le chiffre de
poids faible est
pair. Donc, 3,05 est arrondi à 3,0 et non à 3,1.




Je radote : la norme IEEE définit le stockage et le comportement des
réels sur 32 et 64 bits.

L'auteur a juste choisi un exemple simple en base 10 pour illustrer ses
propos, car c'est plus clair pour un humain normalement constitué qui
manipule rarement les puissances négatives de 2.

Je (re)cite aussi :
"Par exemple, dans un système flottant utilisant la base 10 et deux
nombres significatifs..."

La norme IEEE-754 s'en contrefiche de cet exemple didactique. Elle, tout
ce qui l'intéresse, c'est savoir quoi faire de ce fichu dernier bit (je
te rappele qu'on est en binaire) lorsqu'un calcul ne tombe pas juste.
Elle n'a jamais prétendu vouloir normaliser la notion d'arrondi dans
l'absolu. Là c'est toi qui extrapole.


Tiens, je te redonne la formule pour arrondir un réel à 2 décimales (en
base 10) :
$valeurarrondie = ((int)($valeur*100+0.5))/100;



J'arrondi 3.05 pour l'exemple du document à 1 décimale :

$valeur = 3.05;
$arrondi = ((int)($valeur*10+0.5))/10;
= ((int)( 3.05 *10+0.5))/10;
= ((int)( 30.5 +0.5))/10;
= ((int)( 31 ))/10;
= ( ( 31 ))/10;
= 3.1


On est donc bien d'accord.


CONTRAIREMENT
à ce qui est cité ci-dessus dans le document, qui préconise 3.0 .


Non, le document ne préconise rien du tout pour les calculs décimaux, il
donne juste une analogie simple à comprendre. Il dit même à plusieurs
reprises qu'il existe 4 façons d'arrondir un réel.

La fonction round() de php en a choisi une parmi ces quatre, celle dont
je donne la formule (cf. les spécifications de php). Il s'avère que
c'est la même que celle qui est normalisée pour les calculs financiers,
gros bouffeurs d'arrondis s'il en est, et ce n'est certainement pas un
hasard.

Le problème initial du fil est que cette fonction est *peut-être* buguée
dans certaines versions de php, alors je préconise d'utiliser à la place
la formule explicite.

Maintenant j'ai assez perdu de temps à m'expliquer avec un mur, alors tu
peux répondre si ça fait du bien à ton égo d'avoir le dernier mot, mais
je ne suivrai pas.

Jacques


Avatar
Stephane Santon
Bonjour,

arrondit un résultat « à mi-chemin », on prend celui qui est pair.


La fonction round() de php en a choisi une parmi ces quatre, celle dont
je donne la formule (cf. les spécifications de php). Il s'avère que
c'est la même que celle qui est normalisée pour les calculs financiers,
gros bouffeurs d'arrondis s'il en est, et ce n'est certainement pas un
hasard.

Maintenant j'ai assez perdu de temps à m'expliquer avec un mur, alors tu
peux répondre si ça fait du bien à ton égo d'avoir le dernier mot, mais
je ne suivrai pas.


Dommage que tu ne suives pas, car je suis avide d'information.
Et je ne saurai donc pas selon quelle règle mon pentium arrondit *tous*
les nombres *décimaux* dont la partie décimale est 0,5 à l'entier *PAIR*
le plus proche, précisément comme dans l'exemple donné dans la norme.
De plus, j'ai appris cette règle de l'arrondi "au pair" comme étant la
méthode de "l'arrondi bancaire", et non comme ta formule.

Car si l'on fait la somme de valeurs à partie décimale à 0,5, on a :
1,5 + 2,5 + 3,5 + 4,5 = 12

En arrondissant ces valeurs avant, avec ta formule, soit au-dessus :
2 + 3 + 4 + 5 = 14

En arrondissant au pair le plus proche :
2 + 2 + 4 + 4 = 12.

Ca me parait faire moins d'erreurs.

--
** Anti-Spam : ajouter [usenet] dans l'objet pour ne pas être rejeté.

Cordialement, Stéphane *** http://www.team-santonum.com
Loisirs, nature, arts, technologie : accueil en Charente-Maritime


1 2