Mon algorithme calcule le epsilon para simple précision l'arithmétique à virgule flottante. Il est censé être quelque chose autour de 1.1921e-007. Voici le code :
static void Main(string[] args) {
// start with some small magic number
float a = 0.000000000000000013877787807814457f;
for (; ; ) {
// add the small a to 1
float temp = 1f + a;
// break, if a + 1 really is > '1'
if (temp - 1f != 0f) break;
// otherwise a is too small -> increase it
a *= 2f;
Console.Out.WriteLine("current increment: " + a);
}
Console.Out.WriteLine("Found epsilon: " + a);
Console.ReadKey();
}
En mode débogage, il donne la sortie raisonnable suivante (abrégée) :
current increment: 2,775558E-17
current increment: 5,551115E-17
...
current increment: 2,980232E-08
current increment: 5,960464E-08
current increment: 1,192093E-07
Found epsilon: 1,192093E-07
Cependant, lors du passage en mode release (peu importe avec/sans optimisation !), le code donne le résultat suivant :
current increment: 2,775558E-17
current increment: 5,551115E-17
current increment: 1,110223E-16
current increment: 2,220446E-16
Found epsilon: 2,220446E-16
qui correspond à la valeur de double précision . Je suppose donc que certaines optimisations font que les calculs sont effectués sur des valeurs doubles. Bien sûr, le résultat est faux dans ce cas !
En outre, cela ne se produit que si le ciblage X86 Release dans les options du projet. Encore une fois : l'optimisation activée/désactivée n'a aucune importance. Je suis sur WIN7 64 bit, VS 2010 Ultimate, ciblant .NET 4.0.
Qu'est-ce qui pourrait provoquer ce comportement ? Un problème de WOW ? Comment le contourner de manière fiable ? Comment empêcher le CLR de générer du code qui utilise des calculs en double précision au lieu de calculs en simple précision ?
Note : le passage à "Any CPU" ou même "X64" comme cible de plate-forme n'est pas une option - même si le problème ne se produit pas ici. Mais nous avons quelques bibliothèques natives, dans des versions différentes pour 32/64 bit. La cible doit donc être spécifique.