Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Flottant et résultat

12 réponses
Avatar
loiseauthierry
Bonjour,

Avec JavaScript, le résultat d'un calcul sur des flottants peut sembler
aberrant.

Ainsi, le résultat de :

10.2 - 4.3

retourne

5.8999999999999995

au lieu de

5.9

Je me dis alors qu'une simple calculatrice de poche à trois francs six
sous est bien plus performante... sauf que, en interne, une calculatrice
stocke plus de chiffres qu'elle ne le montre. Elle a en mémoire 16
chiffres (par exemple), mais n'affiche que 14 chiffres... en passant par
un arrondi.

Il suffit donc, pour le JavaScript, de faire quelque chose comme :

function simplifie(v) {
with (Math) {
v=(round(v*pow(10,14)))/pow(10,14);
}
return v;
}

a=10.2;
b=4.3;
c=a-b; // 5.8999999999999995
c=simplifie(c); // 5.9

c=a-b+0.000000007; // 5.900000006999999
c=simplifie(c); // 5.900000007

c=10.2-4.3+0.000000007; // 5.900000006999999
c=simpifie(10.2-4.3+0.000000007); // 5.900000007



Youpi ! Ça marche impeccable, y'a pas de bug... Quoi que !


Prenons un grand entier décimal.

a=100000000010.2;
b=4.3;
...

Là, du coup, il vaut mieux ne pas utiliser simplifie !!!

c=100000000010.2-4.3+0.000000007;

donne 100000000005.9

et

simplifie(c)

donne 100000000005.89998

Argh !

Il faut donc tenir compte du nombre de chiffres dans la partie entière
pour déterminer le nombre de chiffres dans la partie décimale à prendre
en compte pour l'arrondi. (je ne sais pas si je suis clair, là).

Déterminer le nombre de chiffre dans la partie entière :

Math.ceil( Math.log(c)/Math.log(10) )

On modifie donc la function simplifie()



----------------------------------------------------------------------
function simplifie(v) {
var n;
with (Math) {
n=ceil(log(c)/log(10));
v=(round(v*pow(10,15-n)))/pow(10,15-n);
}
return v;
}
----------------------------------------------------------------------



Qu'en pensez-vous ? Olivier ?

Thierry
--
* * __*__ *
* * * -----oOOo---°O°---oOOo------ * *
<http://astrophoto.free.fr> *
* * -------- oOOo oOOo -------- *

10 réponses

1 2
Avatar
loiseauthierry
Thierry Loiseau wrote:

nÎil(log(c)/log(10));


Oups! il fallait lire log(v)
----------------------------------------------------------------------
function simplifie(v) {
var n;
with (Math) {
nÎil(log(v)/log(10));
v=(round(v*pow(10,15-n)))/pow(10,15-n);
}
return v;
}
----------------------------------------------------------------------

Thierry

Avatar
loiseauthierry
Thierry Loiseau wrote:

nÎil(log(c)/log(10));


Oups! il fallait lire log(v)
----------------------------------------------------------------------
function simplifie(v) {
var n;
with (Math) {
nÎil(log(v)/log(10));
v=round(v*pow(10,15-n))/pow(10,15-n);
}
return v;
}
----------------------------------------------------------------------

Thierry

Avatar
Olivier Miakinen

[...]

Qu'en pensez-vous ? Olivier ?


Puisque tu me poses directement la question, j'avoue que je n'en pense
pas grand chose dans le cas général, préférant utiliser les entiers tant
que c'est possible. De retour au bureau je regarderai quand même la
norme ECMAScript pour voir s'il n'y a pas déjà une fonction d'affichage
qui arrondit à N chiffres significatifs (pour éviter de devoir faire une
fonction supplémentaire de normalisation, à base de logarithmes et de
puissances, d'autant que ces fonctions sont elles-mêmes sujettes aux
erreurs d'arrondi).

Avatar
loiseauthierry
Olivier Miakinen <om+ wrote:


[...]

Qu'en pensez-vous ? Olivier ?


Puisque tu me poses directement la question, j'avoue que je n'en pense
pas grand chose dans le cas général, préférant utiliser les entiers tant
que c'est possible.


En fait, ce que je veux faire, c'est une fonction fiable (ou la moins
bancale possible) qui permet de retourner une valeur arrondie à la
manière d'une calculatrice. Bref, une fonction que l'on utiliserait qu'à
la fin d'un calcul (comme il est bon de faire lorsqu'il s'agit
d'arrondi).

De retour au bureau je regarderai quand même la norme ECMAScript pour voir
s'il n'y a pas déjà une fonction d'affichage qui arrondit à N chiffres


A priori, non. Mais je peux me tromper.

significatifs (pour éviter de devoir faire une fonction supplémentaire de
normalisation, à base de logarithmes et de puissances, d'autant que ces
fonctions sont elles-mêmes sujettes aux erreurs d'arrondi).


Voici ici des infos sur la méthode Math :

<http://phrogz.net/objjob/object.asp?id15>

@++ et bon dimanche,
Thierry
--
* * __*__ *
* * * -----oOOo---°O°---oOOo------ * *
<http://astrophoto.free.fr> *
* * -------- oOOo oOOo -------- *


Avatar
YD
Olivier Miakinen <om+ wrote:
De retour au bureau je regarderai quand même la norme ECMAScript pour voir
s'il n'y a pas déjà une fonction d'affichage qui arrondit à N chiffres


A priori, non. Mais je peux me tromper.


Méthode toFixed de l'objet Number ?
(http://phrogz.net/objjob/method.asp?idq6)

--
Y.D.


Avatar
loiseauthierry
YD wrote:

Olivier Miakinen <om+ wrote:
De retour au bureau je regarderai quand même la norme ECMAScript pour voir
s'il n'y a pas déjà une fonction d'affichage qui arrondit à N chiffres


A priori, non. Mais je peux me tromper.


Méthode toFixed de l'objet Number ?
(http://phrogz.net/objjob/method.asp?idq6)


Vous avez toujours réponse à tout, vous !

Merci Yves,

Thierry
--
* * __*__ *
* * * -----oOOo---°O°---oOOo------ * *
<http://astrophoto.free.fr> *
* * -------- oOOo oOOo -------- *



Avatar
loiseauthierry
YD wrote:

Olivier Miakinen <om+ wrote:
De retour au bureau je regarderai quand même la norme ECMAScript pour voir
s'il n'y a pas déjà une fonction d'affichage qui arrondit à N chiffres


A priori, non. Mais je peux me tromper.


Méthode toFixed de l'objet Number ?
(http://phrogz.net/objjob/method.asp?idq6)


----------------------------------------------------------------------
function simplifie(v) {
var n;
with (Math) {
nÎil(log(v)/log(10));
v=round(v*pow(10,15-n))/pow(10,15-n);
}
return v;
}
c0000000010.2-4.3+0.000000007;
c=simplifie(c);
----------------------------------------------------------------------

En effet, pour les exemples précédents, ça fonctionne pile-poil. Yep !

fix=(100000000010.2-4.3+0.000000007).toFixed(14);
fix=parseFloat(fix);

retourne bien 100000000005.9 et

fix=(10.2-4.3).toFixed(14);
fix=parseFloat(fix);

retourne bien 5.9

donc, la function devient... inutile ?

----------------------------------------------------------------------
c0000000010.2-4.3+0.000000007;
c=parseFloat(c.toFixed(14));
----------------------------------------------------------------------

Merci !

Thierry
--
* * __*__ *
* * * -----oOOo---°O°---oOOo------ * *
<http://astrophoto.free.fr> *
* * -------- oOOo oOOo -------- *



Avatar
loiseauthierry
YD wrote:

Olivier Miakinen <om+ wrote:
De retour au bureau je regarderai quand même la norme ECMAScript pour voir
s'il n'y a pas déjà une fonction d'affichage qui arrondit à N chiffres


A priori, non. Mais je peux me tromper.


Méthode toFixed de l'objet Number ?
(http://phrogz.net/objjob/method.asp?idq6)


----------------------------------------------------------------------
function simplifie(v) {
var n;
with (Math) {
nÎil(log(v)/log(10));
v=round(v*pow(10,15-n))/pow(10,15-n);
}
return v;
}
c0000000010.2-4.3+0.000000007;
c=simplifie(c);
----------------------------------------------------------------------

En effet, pour les exemples précédents, ça fonctionne pile-poil. Yep !

fix=(100000000010.2-4.3+0.000000007).toFixed(14);
fix=parseFloat(fix);

retourne bien 100000000005.9 et

fix=(10.2-4.3).toFixed(14);
fix=parseFloat(fix);

retourne bien 5.9

donc, la function devient... inutile :-)))

----------------------------------------------------------------------
c0000000010.2-4.3+0.000000007;
c=parseFloat(c.toFixed(14));
----------------------------------------------------------------------

Merci !

Thierry
--
* * __*__ *
* * * -----oOOo---°O°---oOOo------ * *
<http://astrophoto.free.fr> *
* * -------- oOOo oOOo -------- *



Avatar
YD
[...]
donc, la function devient... inutile :-)))
----------------------------------------------------------------------
c0000000010.2-4.3+0.000000007;
c=parseFloat(c.toFixed(14));
----------------------------------------------------------------------


Je n'ai pas tout compris ce que tu cherches exactement mais
attention, toutefois. Quelques résultats un peu surprenants se
produisent avec certaines valeurs. Pour 0.045.toFixed(2) Firefox
donne 0.04 alors que IE donne 0.05... Ce sujet avait été évoqué
il y a bien longtemps ici même.
(voir : http://ygda.free.fr/decim.htm)

--
Y.D.

Avatar
loiseauthierry
YD wrote:

[...]
donc, la function devient... inutile :-)))
----------------------------------------------------------------------
c0000000010.2-4.3+0.000000007;
c=parseFloat(c.toFixed(14));
----------------------------------------------------------------------


Je n'ai pas tout compris ce que tu cherches exactement mais


Eviter de tomber sur des "aberration" comme l'exemple donné
précédemment, ie 5.899999... au lieu de 5.9

attention, toutefois. Quelques résultats un peu surprenants se
produisent avec certaines valeurs. Pour 0.045.toFixed(2) Firefox
donne 0.04 alors que IE donne 0.05... Ce sujet avait été évoqué
il y a bien longtemps ici même.
(voir : http://ygda.free.fr/decim.htm)


Ah, effectivement. Avec Safari, le résultat est 0.05 ainsi que IE 5.2
Mac. Par contre, avec FF, 0.035 retourne 0.04

Bug de FF ?

Thierry
--
* * __*__ *
* * * -----oOOo---°O°---oOOo------ * *
<http://astrophoto.free.fr> *
* * -------- oOOo oOOo -------- *


1 2