Bonjour
je souhaiterais pouvoir faire une boucle avec comme index, un nombre commençant par 0.000 , comment s'y prendre pour que ce dernier soit pris en compte et me sort 0.001,0.002,0.003 etc... ?
merci d'avance.
Version imprimable
Bonjour
je souhaiterais pouvoir faire une boucle avec comme index, un nombre commençant par 0.000 , comment s'y prendre pour que ce dernier soit pris en compte et me sort 0.001,0.002,0.003 etc... ?
merci d'avance.
Naïvement :
Mais je préfère, et recommande :Code:
1
2
3 double x; /* Je ne vois aucune raison de preferer naturellement float a double */ for(x = 0.000; x <= 1.000; x += 0.001) /* Le traitement */ ;
Code:
1
2
3
4
5
6
7 int i; double x; for(i = 0; i <= 1000; i++) { x = i / 1000.0; /* Le traitement */ ; }
Voire pour effectuer un traitement sans devoir passer par des variables temporaires.
Exemple :
C'est pour moi plus efficace que :Code:
1
2
3
4
5
6
7 double r; double var = 0.25 for (r = 0.000; r < (90 + var); r += var) { rotation (r); /* On effectue une rotation en degrés */ }
Code:
1
2
3
4
5
6
7
8
9 int cpt; double r = 0.000; double var = 0.25; for (cpt = 0; r < ((90 / var) + 1); cpt++) { r += var; rotation (r); }
Ah ?Citation:
Envoyé par pfeuh
Source : http://www.crossware.com/datasheets/c8051nt.htmCitation:
8051 specific language extensions are described below.
Data sizes
The compiler uses the following sizes for the various C data types:
(...)
float: 4 bytes (32 bits)
double: 8 bytes (64 bits)
(...)
De toute façon j'ai pas dit que le type float ne servait à rien, que ça soit sur 8051 ou ailleurs, mais que s'il n'y a pas de raisons très particulières vaut mieux utiliser double plutôt que float.
Bsans : franchement, utiliser un type flottant comme indice dans une boucle n'est pas une très bonne idée à cause de l'imprécision de ces types. Puis, je doute que le second code est plus efficace que le premier mais de toute façon, que ça soit vraiment le cas où pas, tes deux techniques ne sont pas une bonne façon de faire une rotation animée, toujours à cause de l'imprécision des réels. La bonne méthode est :
Code:
1
2
3
4
5
6 int i; double delta_angle = 0.25; for(i = 0; i <= 360; i++) { set_angle(i * delta_angle) }
C'était juste une illustration du fait qu'on puisse avoir besoin d'autre chose qu'un "compteur classique" dans une boucle.
Je ne dis pas que c'est bien ou pas, juste que c'est faisable et que ça peut servir dans certains cas.
Moi, je suis également partisan de l'utilisation de float avant les double. D'abord parce que c'est généralement tout l'un ou tout l'autre : soit l'exposant d'un float permet d'aller suffisamment loin avec une précision honorable, soit les imprécisions se cumulent de manière exponentielle, lors de multiplications successives par exemple, et dans ce cas, passer de float à double n'apporte pas grand chose de plus : le nombre d'opérations possible est simplement doublé et non pas élevé au carré.
L'utilisation de double a un coût. Cela fait deux transactions de bus au lieu d'une sur les machines 32 bits, même si le coprocesseur gère nativement les formats 64 bits, et cela double virtuellement la mémoire consommée. Tant que l'on utilise quelques float ou double par ci, par là, ça n'a pas trop de conséquence, mais pour ceux qui ont l'habitude d'utiliser des réels partout, et dans les langages objets tels que le C++, par exemple, où les classes sont faites pour hériter des précédentes, ça peut grossir très vite.
D'une manière générale, on devrait choisir un format ou un autre qu'à partir du moment où l'on est certain de connaître ses limites, spécialement avec les nombres à virgule flottante (c'est beaucoup plus facile avec les entiers), sinon, on est incapable de prévoir quand une erreur sera susceptible de se produire. Et comme, dans ce cas, elle se traduira par un calcul erroné plutôt que par une erreur d'exécution (exception, segfault…), ses implications peuvent devenir dramatiques.
Obsidian : Considère la boucle suivante :
Parce que i ne prend que des valeurs compises entre 0 et 10, tu me recommanderais d'utiliser le type char pour i plutôt que int ? D'accord j'ai pris un exemple d'un faible intérêt, mais l'idée est bien là : L'ergonomie au niveau du code, c'est aussi important. Il ne faut pas toujours être maniac de performance (mais j'admets bien que dans certains cas il faut l'être, en OpenGL par exemple je n'utilise QUE des float). En langage C, double est aux réels ce que int est aux entiers. C'est pourquoi je conseille de toujours utiliser double au lieu de float, sauf quand il y a de raisons sérieuses de préférer float.Code:
1
2
3 int i; for(i = 0; i < 10; i++) printf("Bonjour.\n");
Non (et encore) mais il me viendrait encore moins à l'idée de recommander aux gens d'utiliser systématiquement des « signed long long » à la place de tous les int parce qu'ils sont plus grands. L'exemple est pourtant beaucoup plus comparable, à commencer par les largeurs des champs qui sont identiques sur les machines actuelles. On pourrait aussi arguer que 2 milliards (pour un entier signé), c'est beaucoup mais ce n'est pas astronomique et peut être atteint dans la vie courante.
Or, justement, la manie d'utiliser double systématiquement ne se « justifie » que par cela. Il n'est ni plus ni moins ergonomique d'utiliser le mot-clé float plutôt que double dans un programme, surtout dans la mesure où les formats sont normalisés et fixes, ce qui évite bien des surprises.
Bonjour à tous,
merci pour vos réponses, car cela m'a permis de régler mon problème.
J'ai juste une question pour melem, n'ayant pas trop besoin de précision j'ai utilisé dans mon programme, la version "naive" de la boucle :
Par contre pour la 2ème méthode je ne vois pas comment utilisé la varible X ? peux tu me dire comment l'intégrer dans mon code ? merci.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <stdio.h> #define G 9.81 #define N 0.16 int main(void) { double t; /* Temps en seconde */ float m; /* Longueur en m */ printf("\t t(s)\t(1/2)gt^2(m)\n"); printf("\t===========================\n"); for (t=0.00; t<=N; t += 0.01) { m = 0.5*G*t*t; printf("\t %.3f \t %.3f\n", t , m); } return 0; }
Je ne recommande systématiquement (par défaut) ni long, ni long long (C99), mais int. Tout simplement parce que le type entier par défaut du C. L'expression 1 par exemple n'est ni un char, ni un unsigned long, ni un long long, mais un int. sizeof(1) vaut sizeof(int). Quand tu écris long long n = 1, ça ne marche pas (en version archi extrêmiste : ça ne compile pas) tout de suite ! Dans une telle expression, le 1, qui est un int, est tout d'abord converti en 1LL, qui est enfin bien un long long. Cette conversion se fait automatiquement, implicitement, pendant la compilation. Si le C ne supportait pas les conversions implicites, alors long long n = 1 ne passerait pas à la compilation, il fallait écrire long long n = 1LL. C'est pareil avec les flottants. 1.0 n'est ni un float, ni un long double, mais un double. 1.0f par contre est bien un float et 1.0L est un long double.Citation:
Envoyé par Obsidian
sedawk :
Code:
1
2
3
4
5
6
7
8
9
10
11
12 #define _N_ 16 ... int i; double t; for(i = 0; i <= _N_; i++) { t = i / 100.0; m = 0.5 * G* t * t; ... } ...
t = i / 100.0;
Tout à fait. C'est ma façon de penser aussi. Sauf qu'en dessous de 16 bits, le int est pénalisant, car formé de deux bytes. Pour le cas d'une boucle de 0 à 10, je prendrais comme index un unsigned char pour un processeur 8 bits. Mais comme je sens bien que pour la majorité d'entre vous il n'y a pas de vie possible en dessous de 32 bits, je sors. :lol:
Enfin, sur une plate-forme 8 bits, je m'attendrais à avoir ceci:
- char -> 8 bits
- short -> 8 bits
- int -> 8 bits
- long -> 16 bits
Ensuite, si on passe à une plate-forme 16 bits...
Ce n'est pas possible (enfin si la plate-forme respecte la norme bien entendue) : http://c.developpez.com/faq/?page=ty...S_taille_types
Ah, j'avais oublié les tailles minimales :-(