Почему у меня возникают арифметические расхождения между режимами отладки и выпуска и как я могу их исправить? - PullRequest
4 голосов
/ 17 августа 2011

В моей программе этот фрагмент:

  trace.log(
   String.Format("a= {0:R} b= {1:R} a<b= {2}", 
    b.GetPixel(447, 517).GetBrightness(), (100F / 255F),
    b.GetPixel(447, 517).GetBrightness() < (100F / 255F))
  );

выводит это в Debug \ prog.exe:

 a= 0.392156869 b= 0.392156869 a<b= False

, но этот другой результат в Release \ prog.exe:

 a= 0.392156869 b= 0.392156869 a<b= True

Может кто-нибудь объяснить, почему одни и те же операнды дают другой результат сравнения?И порекомендовать средство, идеально для всей программы, такое как переключатель компилятора?Спасибо.

РЕДАКТИРОВАТЬ: Уточнение: вышеупомянутые результаты от запуска Debug \ prog.exe и Release \ prog.exe в проводнике Windows.

РЕДАКТИРОВАТЬ: Дополнительная информация: при выполнении из VS «Start Debugging» выдает False (т. Е. Точный результат, такой же, как запущенный WE Debug \ prog.exe), а «Start без отладки» дает True (т. Е. Неточный результат, такой же, какWE-запущенный выпуск \ prog.exe.

РЕДАКТИРОВАТЬ: Альтернативные тестовые случаи с заменой литералов

Эти два случая

  trace.log(
   String.Format("a= {0:R} b= {1:R} a<b= {2}",
    0.392156869F, 0.392156869F, 
    0.392156869F < 0.392156869F)
  );
  trace.log(
   String.Format("a= {0:R} b= {1:R} a<b= {2}",
    0.392156869F, (100F / 255F),
    0.392156869F < (100F / 255F))
  );

не показывают расхожденийв выходных данных отладки и выпуска. В этом случае:

  trace.log(
   String.Format("a= {0:R} b= {1:R} a<b= {2}",
    b.GetPixel(447, 517).GetBrightness(), 0.392156869F,
    b.GetPixel(447, 517).GetBrightness() < 0.392156869F)
  );

показывает то же самое расхождение (и неточность в версии), что и в исходном тестовом примере.

РЕДАКТИРОВАТЬ: запоздалое минимальное тестированиепроблема

Color c = Color.FromArgb( 255, 100, 100, 100 );
trace.log(
 String.Format("a= {0} b= {1} a<b= {2}",
 c.GetBrightness(), 0.392156869F,
 c.GetBrightness() < 0.392156869F)
);

выводит этот правильный результат в Debug \ prog.exe:

 a= 0.392156869 b= 0.392156869 a<b= False

, но этот неверный результат в Release \ prog.exe:

 a= 0.392156869 b= 0.392156869 a<b= True

РЕДАКТИРОВАТЬ: Средства правовой защиты

1) Из ответа Петра ниже:

trace.log(
 String.Format("a= {0:R} b= {1:R} a<b= {2}",
  c.GetBrightness(), 0.392156869F, 
  c.GetBrightness().CompareTo(0.392156869F)<0)
);

2) От ChrisJJ, спрашивающий ( ОБНОВЛЕН * ):

float comp = c.GetBrightness();
trace.log(
 String.Format("a= {0:R} b= {1:R} a<b= {2}", 
 comp, 0.392156869F,
 comp < 0.392156869F)
);

Я думаю, что это добавляет доказательство ошибки компилятора режима выпуска.

1 Ответ

7 голосов
/ 17 августа 2011

Скорее всего, это результат различных правил с плавающей запятой между режимом отладки и режимом выпуска (см. здесь и здесь ).

Обновление:

Благодаря вашему новому обновлению вопроса я смог воспроизвести проблему на моей машине (64-битная Windows).Это происходит только при установке платформы на X86;платформы X64 и AnyCPU показывают правильный результат в режиме выпуска.Возможно, когда используется платформа X86, общеязыковая среда выполнения применяет эмуляцию X86 на 64-разрядных машинах и, по-видимому, ошибается в операторе сравнения.

Однако я нашел возможный обходной путь: используйте CompareTo вместо "<Операторы "и">, например:

c.GetBrightness().CompareTo(0.392156869F)<0

На моей машине это даст те же правильные результаты в X86, что и в X64 и AnyCPU.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...