Мой алгоритм вычисляет эпсилон для одинарной точности арифметики с плавающей запятой.Это должно быть что-то около 1.1921e-007.Вот код:
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();
}
В режиме отладки он дает следующий разумный вывод (сокращенно):
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
Однако при переходе в режим разблокировки (независимо от того, с / безоптимизация!), код дает следующий результат:
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
, что соответствует значению для двойной точности .Поэтому я предполагаю, что некоторые оптимизации приводят к тому, что вычисления выполняются с двойными значениями.Конечно, результат неправильный в этом случае!
Также: это происходит только при нацеливании X86 Release в опциях проекта.Опять же: оптимизация вкл / выкл не имеет значения.Я использую 64-разрядную версию WIN7 VS 2010 Ultimate, ориентированную на .NET 4.0.
Что может вызвать такое поведение?Какая-то ВАУ проблема?Как обойти это надежным способом?Как запретить CLR генерировать код, который использует двойную точность вместо вычислений с одинарной точностью?
Примечание: переключение на «Любой ЦП» или даже «X64» в качестве целевой платформы не вариант - даже если проблема здесь не возникает.Но у нас есть некоторые нативные библиотеки, в разных версиях для 32/64 бит.Таким образом, цель должна быть конкретной.