Logo du forum
 

Forum TT-Hardware

| Inscription | | Recherche | | FAQ | | Accueil | | Liste des membres |
| Calendrier |
 
Vous n'êtes pas identifié! [Connexion] ou [Inscription] Forum » Programmation » [C / C++ / C#] » drôle de comportement...
Login Mot de passe

1 visiteurs sur ce topic (0 membre(s), 1 invité(s) )

Auteur
Sujet : drôle de comportement...
Black_Knight



 






Message du 23-06-2006 @ 8:09


bonjour.

Je débute la programmation en C, et j'ai fait un petit programme de conversion celsius <--> farhneit (comment on écrit ça!??!!)

le voila:

Code :

#include <stdio.h>

main()
{
   float fahr, celsius;
   float lower, upper, step;
   FILE* fichier = NULL;   

   fichier = fopen("conversion.txt", "w");
   lower = 0;
   upper = 300;
   step = 0.01;
   
   celsius = lower;
   while (celsius <= upper) {
      fahr = ( celsius / 5 * 9 ) + 32;
      printf("%ft%fn", celsius, fahr);
      fprintf(fichier, "%ft%fn", celsius, fahr);
      celsius = celsius + step;
   }
   return 0;
getchar();
}



mais je ne sais pas pourquoi, mais à partir de 0.83 celsius, voici ce que j'obtient:

Code :

0.820000   33.475998
0.830000   33.493999
0.839999   33.511997
0.849999   33.529999



je ne comprend pas d'où viennent les 9. pourtant, 0.83 + 0.01 donne bient 0.84, ce n'est pas une erreur d'arrondissement car il a 4 zéros de jeu. à la fin du ficher texte, voici ce que j'obtient:

Code :

299.981476   571.966675
299.991486   571.984680



ce qui est quand même assez loin du 300 attendu.


merci pour vos réponses.
- Haut de page -
noxyd



 






Message du 23-06-2006 @ 8:42

essaye déja en remplacant tes %f par %.2f pour voir.
- Haut de page -
$AX$



 






Message du 23-06-2006 @ 8:50

Pas mieux...

... ou remplace tes "float" par des "double"
- Haut de page -
UdoBoth



 






Message du 23-06-2006 @ 10:41

C'est Mr. Farenheit....

C'est tout le problème de la représentation des réels en binaire, du nombre de chiffres significatifs alloués à la mantisse (les nombres sont sous la forme mantisse * exposant - choix float <-> double).
Si le compilateur C n'optimise pas les opérations, il peut y avoir intérêt à poser l'opération dans l'ordre * puis /
bien qu'elle soit commutative en théorie.
300 ou 299,991 c'est pareil à quelques 10 puissance -5 près (en "double" ce sera peut-être mieux, sinon forcer l'arrondi)
Courage, le calcul scientifique est plein de surprises....

- Haut de page -
Black_Knight



 






Message du 23-06-2006 @ 18:28

j'ai essayé en double, et les réponses sont exactes, en effet. Mais je ne comprend toujours pas trop pourquoi ça ne marche pas en float...
- Haut de page -
marsu_381



 






Message du 23-06-2006 @ 23:44

une autre hypotèse, au niveau de cette ligne :
fahr = ( celsius / 5 * 9 ) + 32

essaye de remplacer les entiers par des décimaux.

- Haut de page -
Black_Knight



 






Message du 24-06-2006 @ 5:26

Citation du message de marsu_381 :

une autre hypotèse, au niveau de cette ligne :
fahr = ( celsius / 5 * 9 ) + 32

essaye de remplacer les entiers par des décimaux.



j'ai essayer, mais rien à faire. le résultat est exactement le même que lors du premier post. Mais je crois que cette technique fonctionne uniquement lors que le résultat est tronqué. Ainsi, en divisant par un nombre à virgule, le résultat n'est pas tronqué car l'ordinateur le voit une division de 2 nombres de même type.

EDIT: Une chose est certaine, ce n'est pas la faute d'un compilateur capricieux. j'ai tester avec Open Watcom, Digital Mars ainsi que SilverFrost FTN95. (et étonnement, FTN95, un compilateur fortran, produit l'exécutable le moins volumineux.)

[message édité le 24-06-2006 @ 5:40 Par Black_Knight]
- Haut de page -
UdoBoth



 






Message du 25-06-2006 @ 12:11

Bonjour,

Il ne faut pas se laisser abuser par la valeur décimale des nombres et croire que parce qu'on additionne 0.01 + 0.01 à l'infini (jusqu'à 300 ici...) le résultat DOIT tomber juste en décimal. Le CPU du PC ne compte pas en décimal...
Les nombres sont convertis en binaire -> calcul -> reconversion en décimal pour présentation.
Le calcul avec des ENTIERS tombera juste tant que les nombres (et les résultats intermédiaires...) ne dépassent pas +- 32767 (avec mots de 16 bits "WORD"), +- 2147483647 (avec mots de 32 bits "INTEGER"), encore plus en mots de 64 bits...
Le calcul avec des RéELS est un faux ami.... selon le nombre de bits alloués à la MANTISSE la représentation du nombre de départ peut déjà être approximative dès la conversion en binaire. Le réel est stocké sous la forme
(a 1/2 + b 1/4 + c 1/8 + d 1/16 + e.....) * 2**n avec a, b, c, d.... valant 0 ou 1, et n limité au format de l'EXPOSANT de 2 qui multiplie la mantisse.
Les TYPES de variables FLOAT, DOUBLE, LONG DOUBLE correspondent à des formats de plus en plus généreux en nombre de bits alloués pour la mantisse et l'exposant.
La conséquence porte sur le nombre de chiffres significatifs du résultat. Il est illusoire de dépasser 4 chiffres en FLOAT, mais l'ordre de grandeur est bon. Il convient donc de limiter l'affichage au nombre de chiffres qui ont un sens !

COMPLEMENT
La norme IEEE 754 puis 854 définit la représentation flottante des réels (voir avec Google...)
Est-ce que ton compilateur génère des "FLOAT" avec 23 bits de mantisse ou moins ?
Le réel 0.01 n'a pas de contrepartie exacte en flottant, une erreur systématique s'accumule donc à chaque addition et finit par se voir lors de la conversion en décimal.


[message édité le 25-06-2006 @ 18:45 Par UdoBoth]
- Haut de page -
Gnux



 






Message du 25-06-2006 @ 19:17

Si tu veux plus de détails (voir les chapitres 1 & 2) : http://www.ulb.ac.be/di/map/gbonte/InfoF205.html#contenu
Ce n'est pas une blague, le cours est abordable ! :)

- Haut de page -
Black_Knight



 






Message du 26-06-2006 @ 18:50

merci énormément à vous deux, je crois que je commence à comprendre... :D
- Haut de page -

Plan du forum | Contacter l'administrateur

Powered by SoulBB 3.0.1
© Soulmanto, 2003-2006

Valid XHTML 1.0 Transitional

Page générée en 0.132 secondes