Qui a dit que l'ordre de sommation est flottant n'importait pas ??
Voici un petit simulation vous devrait vous convaincre du contraire !
La simulation est la suivante : il y a des masses dans une "arene",
delimitee par un petit cercle, la dedans les masses ne subissent
aucune force exterieures, mais interagissent entre elles suivant
des forces repulsives en 1/r^2 (types gravitationnelles) et des forces
attractives en r^1 (types elastiques), et en dehors de ce cercle
interieur, une force qui derive d'un potentiel et qui a tendance
a ramener toute particule qui sort du cercle dans celui-ci
c'est en gros un "mur" circulaire, pour plus d'information voir
ma source precedente (simulation d'un rebond sur un mur)
Bref tout ceci pour simuler une "bouillie" de forces...
La subtilite de cette source est que je presente deux simulations :
il y a plein de forces, et je dois calculer leur somme
(puisque le principe fondamental de la dynamique stipule de masse fois
acceleration egale somme des forces)
Mais la sommation ne se fait pas de la meme maniere dans les deux
simulations... certains diront que ca n'a pas d'importance... que nenni !
il y a une bonne et une mauvaise maniere de sommer des flottants, la preuve :
les deux situations pourtant initialement identiques dans leur description
divergent au bout de quelques secondes (cf capture d'ecran, les boules rouges
sont censees toujours etre exactement sous les vertes)
La bonne methode pour sommer est de toujours sommer les deux quantitees
qui ont la plus petite valeur absolue...
Ne chipotez pas !! un jour si vous voulez faire une simulation d'une galaxie,
alors vous aurez besoin de sommer des forces et vous aurez ce probleme de
stabilite numerique...
De plus la simulation en soi est tres amusante non ? elle correspond a rien du tout
mais ca fait jolie a voir evoluer...
Convaincu(e) ?
Source / Exemple :
//-------------------------------------------------
double funcSumStupid(double *p,int n)
{
double sum;
int k;
sum = 0.;
// algorithme stupide, on somme dans l'ordre que l'on nous a donne les valeurs
for(k=0;k<n;k++)
{
sum += p[k];
}
return sum;
}
//----------------------------------------------------------
int cmpDouble(void *key1,void *key2,void *param)
{
double a,b;
UNUSED_PARAMETER(param);
a = fabs(*(double*)key1);
b = fabs(*(double*)key2);
if(a > b) return CMP_MORE;
else if(a < b) return CMP_LESS;
else return CMP_EQUAL;
} // cmpDouble()
//-------------------------------------------------
double funcSumNotStupid(double *p,int n)
{
int k;
// on trie les nombres par ordre croissant de leur valeur absolue
QuickSortArray(double,p,n,cmpDouble,NULL);
for(k=0;k<n-1;k++)
{
int i;
p[k+1] += p[k]; // on somme les deux plus petits ...
i = k+1;
// ... puis on fait remonter cette somme a sa bonne place
// pour que les valeurs soient toujours triees selon
// leur valeur absolue
while(i < n-1 && fabs(p[i]) > fabs(p[i+1]))
{
SwapDouble(p+i,p+i+1);
i ++;
}
}
// la somme calculee telle que l'on a minimise les erreurs d'arrondis
return p[n-1];
}
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.