Tout d'abord excusé moi si je ne suis pas au bon endroit pour ma question.
Je suis présentement un cours de calcul numérique et je dois programmer une méthode bien précise (Runge-Kutta pour ceux que cela pourrait intéresser).
Si je fais
double j = 1 * 0.1;
mon compilateur (VC++ .NET 2003) me donne comme valeur ceci : 0.10000000000000001
Le 1 de la fin fait en sorte que je cumule une erreur tout au long du déroulement qui s'amplifie bien entendu.
Quelqu'un peut m'expliquer comment résoudre cette impasse ?
En gros, le problème vient du fait qu'un processeur calcule en binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
2 solutions: - si tu connais la précision nécessaire ("le nombre de chiffres après la virgule") et qu'elle est constante, tu peux utiliser des virgules fixes, pratiquement, tu manipules des int, en fixant arbitrairement leur valeur. (note: attention au multiplication). - si c'est variable, il te faut créer une nouvelle structure de donnée permettant de représenter les nombres décimaux. Certains langage fournissent cela en natif, il faut donc voir ce que tu utilises comme langage.
ps: cette question n'est pas vraiment de la programmation windows. re-ps: ce n'est pas ton compilo, mais ton CPU la source d'erreur.
Tout d'abord excusé moi si je ne suis pas au bon endroit pour ma
question.
Je suis présentement un cours de calcul numérique et je dois
programmer une méthode bien précise (Runge-Kutta pour ceux que cela
pourrait intéresser).
Si je fais
double j = 1 * 0.1;
mon compilateur (VC++ .NET 2003) me donne comme valeur ceci :
0.10000000000000001
Le 1 de la fin fait en sorte que je cumule une erreur tout au long du
déroulement qui s'amplifie bien entendu.
Quelqu'un peut m'expliquer comment résoudre cette impasse ?
En gros, le problème vient du fait qu'un processeur calcule en binaire,
un nombre n'est donc N*10^qqch mais N*2^qqch.
2 solutions:
- si tu connais la précision nécessaire ("le nombre de chiffres après la
virgule") et qu'elle est constante, tu peux utiliser des virgules fixes,
pratiquement, tu manipules des int, en fixant arbitrairement leur
valeur. (note: attention au multiplication).
- si c'est variable, il te faut créer une nouvelle structure de donnée
permettant de représenter les nombres décimaux. Certains langage
fournissent cela en natif, il faut donc voir ce que tu utilises comme
langage.
ps: cette question n'est pas vraiment de la programmation windows.
re-ps: ce n'est pas ton compilo, mais ton CPU la source d'erreur.
Tout d'abord excusé moi si je ne suis pas au bon endroit pour ma question.
Je suis présentement un cours de calcul numérique et je dois programmer une méthode bien précise (Runge-Kutta pour ceux que cela pourrait intéresser).
Si je fais
double j = 1 * 0.1;
mon compilateur (VC++ .NET 2003) me donne comme valeur ceci : 0.10000000000000001
Le 1 de la fin fait en sorte que je cumule une erreur tout au long du déroulement qui s'amplifie bien entendu.
Quelqu'un peut m'expliquer comment résoudre cette impasse ?
En gros, le problème vient du fait qu'un processeur calcule en binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
2 solutions: - si tu connais la précision nécessaire ("le nombre de chiffres après la virgule") et qu'elle est constante, tu peux utiliser des virgules fixes, pratiquement, tu manipules des int, en fixant arbitrairement leur valeur. (note: attention au multiplication). - si c'est variable, il te faut créer une nouvelle structure de donnée permettant de représenter les nombres décimaux. Certains langage fournissent cela en natif, il faut donc voir ce que tu utilises comme langage.
ps: cette question n'est pas vraiment de la programmation windows. re-ps: ce n'est pas ton compilo, mais ton CPU la source d'erreur.
re-ps: ce n'est pas ton compilo, mais ton CPU la source d'erreur.
Par curiosité, j'ai fais le test sous Visual Studio Net et Visual 6, sur la même machine.
Dans le premier cas : double j = 0.1; donne 0.10000000000000001 alors qu'avec Visual 6 j'obtiens 0.1
Les 2 compilateurs semblent donc différents.
Fred D.
Enlevez NoSpam de mon adresse pour me répondre
Manuel Leclerc
Philippe Massicotte a écrit :
Si je fais
double j = 1 * 0.1;
mon compilateur (VC++ .NET 2003) me donne comme valeur ceci : 0.10000000000000001
Le 1 de la fin fait en sorte que je cumule une erreur tout au long du déroulement qui s'amplifie bien entendu.
Quelqu'un peut m'expliquer comment résoudre cette impasse ?
La méthode bourrin de chez bourrin mais qui fonctionne assez bien dans un environnement d'informatique de gestion, peut être peux-tu t'en inspirer, même si ton truc a l'air plutôt scientifique/industriel.
Passe par une représentation sous forme de chaînes de caractères en demandant une précision de quelques chiffres inférieures à la précision de ta représentation flottantes. sprintf/sscanf après chaque calcul. Avec ça, tu peux cumuler autant d'opération bancaires que tu veux sans te retrouver avec des centimes en "génération spontanée". Mais, je t'avais prévenu, c'est bourrin de chez bourrin :-). Et bonjour les perfs.
Travailler en entier peut aussi convenir d'ailleurs. Ca dépends du nombres de digit significatifs que tu veux, et des opérations a effectuer.
Il y aussi peut être une fonction d'arrondi, tout simplement ! mais je connais très mal le couple C/flottants comme tu viens peut être de t'en rendre compte :-)
Philippe Massicotte a écrit :
Si je fais
double j = 1 * 0.1;
mon compilateur (VC++ .NET 2003) me donne comme
valeur ceci : 0.10000000000000001
Le 1 de la fin fait en sorte que je cumule une erreur
tout au long du déroulement qui s'amplifie bien entendu.
Quelqu'un peut m'expliquer comment résoudre cette impasse ?
La méthode bourrin de chez bourrin mais qui fonctionne assez
bien dans un environnement d'informatique de gestion, peut
être peux-tu t'en inspirer, même si ton truc a l'air
plutôt scientifique/industriel.
Passe par une représentation sous forme de chaînes de caractères
en demandant une précision de quelques chiffres inférieures à la
précision de ta représentation flottantes.
sprintf/sscanf après chaque calcul. Avec ça, tu peux cumuler autant
d'opération bancaires que tu veux sans te retrouver avec des
centimes en "génération spontanée". Mais, je t'avais prévenu,
c'est bourrin de chez bourrin :-). Et bonjour les perfs.
Travailler en entier peut aussi convenir d'ailleurs. Ca dépends
du nombres de digit significatifs que tu veux, et des opérations
a effectuer.
Il y aussi peut être une fonction d'arrondi, tout simplement !
mais je connais très mal le couple C/flottants comme tu viens
peut être de t'en rendre compte :-)
mon compilateur (VC++ .NET 2003) me donne comme valeur ceci : 0.10000000000000001
Le 1 de la fin fait en sorte que je cumule une erreur tout au long du déroulement qui s'amplifie bien entendu.
Quelqu'un peut m'expliquer comment résoudre cette impasse ?
La méthode bourrin de chez bourrin mais qui fonctionne assez bien dans un environnement d'informatique de gestion, peut être peux-tu t'en inspirer, même si ton truc a l'air plutôt scientifique/industriel.
Passe par une représentation sous forme de chaînes de caractères en demandant une précision de quelques chiffres inférieures à la précision de ta représentation flottantes. sprintf/sscanf après chaque calcul. Avec ça, tu peux cumuler autant d'opération bancaires que tu veux sans te retrouver avec des centimes en "génération spontanée". Mais, je t'avais prévenu, c'est bourrin de chez bourrin :-). Et bonjour les perfs.
Travailler en entier peut aussi convenir d'ailleurs. Ca dépends du nombres de digit significatifs que tu veux, et des opérations a effectuer.
Il y aussi peut être une fonction d'arrondi, tout simplement ! mais je connais très mal le couple C/flottants comme tu viens peut être de t'en rendre compte :-)
Philippe Massicotte
"Quentin Pouplard" a écrit dans le message de news:
En gros, le problème vient du fait qu'un processeur calcule en binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
Ah merci de l'explication !
2 solutions: - si tu connais la précision nécessaire ("le nombre de chiffres après la virgule") et qu'elle est constante, tu peux utiliser des virgules fixes, pratiquement, tu manipules des int, en fixant arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici. En fait, je voudrait avoir une précision de 10 nombres après la virgule.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
Merci encore :)
Phil
"Quentin Pouplard" <poubelle@alrj.org> a écrit dans le message de
news:26_2004_145213_2144018275_MYOE@news.free.fr...
En gros, le problème vient du fait qu'un processeur calcule en binaire,
un nombre n'est donc N*10^qqch mais N*2^qqch.
Ah merci de l'explication !
2 solutions:
- si tu connais la précision nécessaire ("le nombre de chiffres après la
virgule") et qu'elle est constante, tu peux utiliser des virgules fixes,
pratiquement, tu manipules des int, en fixant arbitrairement leur
valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici. En fait, je voudrait avoir
une précision de 10 nombres après la virgule.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
"Quentin Pouplard" a écrit dans le message de news:
En gros, le problème vient du fait qu'un processeur calcule en binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
Ah merci de l'explication !
2 solutions: - si tu connais la précision nécessaire ("le nombre de chiffres après la virgule") et qu'elle est constante, tu peux utiliser des virgules fixes, pratiquement, tu manipules des int, en fixant arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici. En fait, je voudrait avoir une précision de 10 nombres après la virgule.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
Merci encore :)
Phil
Quentin Pouplard
PendLoup wrote:
Bonjour,
"Quentin Pouplard" wrote
> re-ps: ce n'est pas ton compilo, mais ton CPU la source d'erreur.
Par curiosité, j'ai fais le test sous Visual Studio Net et Visual 6, sur la même machine.
Dans le premier cas : double j = 0.1; donne 0.10000000000000001 alors qu'avec Visual 6 j'obtiens 0.1
Les 2 compilateurs semblent donc différents.
Quel option de compilation as-tu utilisé sur tes deux compilos?
"Quentin Pouplard" a écrit dans le message de news: > En gros, le problème vient du fait qu'un processeur calcule en > binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
Ah merci de l'explication !
> 2 solutions: > - si tu connais la précision nécessaire ("le nombre de chiffres > après la virgule") et qu'elle est constante, tu peux utiliser des > virgules fixes, pratiquement, tu manipules des int, en fixant > arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici.
Le concept est d'utiliser des entiers, par exemple 100, 1203, etc... et de déterminer arbitraitement que 100 est en fait 1.00 et 1203 est 12.03. Les calculs entiers ne souffrant pas de l'imprécision des flotants, il n'y a plus d'erreur d'arrondi... par contre tu te retrouves avec les limitations des entiers: si tu prends des entiers 32, ça ne va au mieux que jusqu'à un peu plus de 4 milliards, ce qui ne te permet pas d'avoir 10 chiffres significatif. En bref, cette solution est à rejetée.
En fait, je voudrait avoir une précision de 10 nombres après la virgule.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
Google devrait te fournir quelques lib de gestion de nombre décimaux dans ton langage favoris (peut-être certains pourront te fournir de bon lien; y'a ptêt ça dans boost puisque tu fais du C++), ou tu peux te faire ta propre classe (tu te rappelles le "calcul écrit" qu'on nous apprenait en primaire, et ben c'est le même concept, mais tu vas le faire faire par ton ordi, en choisissant n'importe quelle structure pour représenter ta suite de chiffre).
"Quentin Pouplard" <poubelle@alrj.org> a écrit dans le message de
news:26_2004_145213_2144018275_MYOE@news.free.fr...
> En gros, le problème vient du fait qu'un processeur calcule en
> binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
Ah merci de l'explication !
> 2 solutions:
> - si tu connais la précision nécessaire ("le nombre de chiffres
> après la virgule") et qu'elle est constante, tu peux utiliser des
> virgules fixes, pratiquement, tu manipules des int, en fixant
> arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici.
Le concept est d'utiliser des entiers, par exemple 100, 1203, etc... et
de déterminer arbitraitement que 100 est en fait 1.00 et 1203 est 12.03.
Les calculs entiers ne souffrant pas de l'imprécision des flotants, il
n'y a plus d'erreur d'arrondi... par contre tu te retrouves avec les
limitations des entiers: si tu prends des entiers 32, ça ne va au mieux
que jusqu'à un peu plus de 4 milliards, ce qui ne te permet pas d'avoir
10 chiffres significatif. En bref, cette solution est à rejetée.
En fait, je voudrait
avoir une précision de 10 nombres après la virgule.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple
simple ?.
Google devrait te fournir quelques lib de gestion de nombre décimaux
dans ton langage favoris (peut-être certains pourront te fournir de bon
lien; y'a ptêt ça dans boost puisque tu fais du C++), ou tu peux te
faire ta propre classe (tu te rappelles le "calcul écrit" qu'on nous
apprenait en primaire, et ben c'est le même concept, mais tu vas le
faire faire par ton ordi, en choisissant n'importe quelle structure
pour représenter ta suite de chiffre).
"Quentin Pouplard" a écrit dans le message de news: > En gros, le problème vient du fait qu'un processeur calcule en > binaire, un nombre n'est donc N*10^qqch mais N*2^qqch.
Ah merci de l'explication !
> 2 solutions: > - si tu connais la précision nécessaire ("le nombre de chiffres > après la virgule") et qu'elle est constante, tu peux utiliser des > virgules fixes, pratiquement, tu manipules des int, en fixant > arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici.
Le concept est d'utiliser des entiers, par exemple 100, 1203, etc... et de déterminer arbitraitement que 100 est en fait 1.00 et 1203 est 12.03. Les calculs entiers ne souffrant pas de l'imprécision des flotants, il n'y a plus d'erreur d'arrondi... par contre tu te retrouves avec les limitations des entiers: si tu prends des entiers 32, ça ne va au mieux que jusqu'à un peu plus de 4 milliards, ce qui ne te permet pas d'avoir 10 chiffres significatif. En bref, cette solution est à rejetée.
En fait, je voudrait avoir une précision de 10 nombres après la virgule.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
Google devrait te fournir quelques lib de gestion de nombre décimaux dans ton langage favoris (peut-être certains pourront te fournir de bon lien; y'a ptêt ça dans boost puisque tu fais du C++), ou tu peux te faire ta propre classe (tu te rappelles le "calcul écrit" qu'on nous apprenait en primaire, et ben c'est le même concept, mais tu vas le faire faire par ton ordi, en choisissant n'importe quelle structure pour représenter ta suite de chiffre).
J'ai créer un projet Win32 Application sous Visual 6. Je n'ai rien changé des options. Puis j'ai ouvert ce projet sous Visual Net. A priori les options de compilation sont restées les mêmes.
a+
Fred D.
J'ai créer un projet Win32 Application sous Visual 6. Je n'ai rien changé
des options.
Puis j'ai ouvert ce projet sous Visual Net. A priori les options de
compilation sont restées les mêmes.
J'ai créer un projet Win32 Application sous Visual 6. Je n'ai rien changé des options. Puis j'ai ouvert ce projet sous Visual Net. A priori les options de compilation sont restées les mêmes.
a+
Fred D.
Christian ASTOR
PendLoup a écrit:
Dans le premier cas : double j = 0.1; donne 0.10000000000000001 alors qu'avec Visual 6 j'obtiens 0.1
J'en doute...
double j = 0.1; printf("double=%.17f", j);
Et tape IEEE ds MSDN ou Google, il y a des tonnes d'articles expliquant ce qu'a dit Quentin en long et en large..
PendLoup a écrit:
Dans le premier cas : double j = 0.1; donne 0.10000000000000001
alors qu'avec Visual 6 j'obtiens 0.1
J'en doute...
double j = 0.1;
printf("double=%.17f", j);
Et tape IEEE ds MSDN ou Google, il y a des tonnes d'articles expliquant
ce qu'a dit Quentin en long et en large..
Dans le premier cas : double j = 0.1; donne 0.10000000000000001 alors qu'avec Visual 6 j'obtiens 0.1
J'en doute...
double j = 0.1; printf("double=%.17f", j);
Et tape IEEE ds MSDN ou Google, il y a des tonnes d'articles expliquant ce qu'a dit Quentin en long et en large..
Cyrille \cns\ Szymanski
>> 2 solutions: - si tu connais la précision nécessaire ("le nombre de chiffres après la virgule") et qu'elle est constante, tu peux utiliser des virgules fixes, pratiquement, tu manipules des int, en fixant arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici. En fait, je voudrait avoir une précision de 10 nombres après la virgule.
Ca me paraît ok vu que log2(10^10)3.22...
Il faut donc au moins 34 bits pour représenter un tel nombre. Un double fera l'affaire vu que sa mantisse est stockée sur 52 bits.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
Utiliser double et faire un arrondi à 10^-10 près.
>> 2 solutions:
- si tu connais la précision nécessaire ("le nombre de chiffres après
la virgule") et qu'elle est constante, tu peux utiliser des virgules
fixes, pratiquement, tu manipules des int, en fixant arbitrairement
leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici. En fait, je voudrait
avoir une précision de 10 nombres après la virgule.
Ca me paraît ok vu que log2(10^10)3.22...
Il faut donc au moins 34 bits pour représenter un tel nombre. Un double
fera l'affaire vu que sa mantisse est stockée sur 52 bits.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple
simple ?.
Utiliser double et faire un arrondi à 10^-10 près.
>> 2 solutions: - si tu connais la précision nécessaire ("le nombre de chiffres après la virgule") et qu'elle est constante, tu peux utiliser des virgules fixes, pratiquement, tu manipules des int, en fixant arbitrairement leur valeur. (note: attention au multiplication).
Je ne saisi pas tout à fait votre réponse ici. En fait, je voudrait avoir une précision de 10 nombres après la virgule.
Ca me paraît ok vu que log2(10^10)3.22...
Il faut donc au moins 34 bits pour représenter un tel nombre. Un double fera l'affaire vu que sa mantisse est stockée sur 52 bits.
Si ce n'est pas trop compliqué, pouvez-vous me donner un exemple simple ?.
Utiliser double et faire un arrondi à 10^-10 près.