Причины для NaN в приложении C++, которые не вызывают исключения с плавающей запятой

Чтобы найти причину того, что переменные с плавающей запятой были установлены в NaN в моей программе на C++, я включил такие исключения с плавающей запятой:

#include <fenv.h>
feenableexcept(FE_INVALID | FE_OVERFLOW);

Я знаю, что это работает, потому что когда я пишу:

int val = 0.0/0.0;

в моей программе возникает исключение с плавающей запятой. Но NaN «распространяются» через вычисления с плавающей запятой моей программы, и я понятия не имею, какая переменная сначала устанавливается в NaN.

Какие существуют причины для установки переменной в NaN, которые не вызовут исключения с плавающей запятой?


person Nathan    schedule 22.03.2011    source источник
comment
При добавлении FE_UNDERFLOW я получаю много исключений, когда я умножаю на 0. Может ли потеря значимости действительно вызвать NaN?   -  person Nathan    schedule 22.03.2011
comment
@ Натан Вы уверены, что на самом деле не умножаете на очень маленькое число, близкое к нулю?   -  person Mark B    schedule 22.03.2011
comment
@Nathan: Насколько я читал, да. Взгляните на en.wikipedia.org/wiki/IEEE_754-2008.   -  person Erik    schedule 22.03.2011
comment
@Nathan: Альтернативный способ отследить это - создать функцию isNaN и начать засорять свой код assert(!isNaN(x))   -  person Erik    schedule 22.03.2011
comment
@Nathan @Erik Просто для ясности, вот как вы можете написать isNaN: template‹typename T› bool isNaN(T value) { return value != value; }   -  person SuperElectric    schedule 22.03.2011
comment
@Эрик. Глядя на ссылку, единственное, что касается недополнения, это следующее: результат очень мало (за пределами нормального диапазона) и является неточным. Это не вызывает NaN, не так ли? Я что-то упускаю?   -  person Nathan    schedule 22.03.2011
comment
@Erik, @SuperEletric Да, засорение тестами isNaN возможно. Это то, что я делаю до сих пор. Это очень раздражает, поэтому я ищу альтернативу.   -  person Nathan    schedule 22.03.2011
comment
@Nathan: IIRC есть флаг FE_ALL, сомневаюсь, что это сильно поможет, если вы уже получите исключения для потери значимости.   -  person Erik    schedule 22.03.2011
comment
Недополнение не может генерировать NaN.   -  person Stephen Canon    schedule 28.12.2012
comment
Однако недостаточные и переполнения могут генерировать infs и 0s, которые могут быстро привести к NaNs.   -  person Mike    schedule 23.06.2014


Ответы (2)


Если какой-либо вход имеет тихое значение NaN, это приведет к тому, что результатом почти любой операции с плавающей запятой, которая его использует, будет NaN без возбуждения недопустимого исключения.

Наиболее вероятное объяснение состоит в том, что некоторые данные считываются с неправильного адреса и что считанные данные (которые могут даже не быть данными с плавающей запятой) соответствуют скрытой кодировке NaN. Это может произойти довольно легко, потому что относительно распространенный шаблон 0xffff... кодирует тихий NaN.

person Stephen Canon    schedule 28.12.2012

Вы выполняете какие-либо операции с квадратным корнем? Если вы попытаетесь вычислить квадратный корень из отрицательного числа, как в sqrt (-1), вы получите Nan. В этом случае вы должны получить исключение «Недопустимая операция». Вы уверены, что правильно перехватываете все исключения? Кажется, что где-то в вашем коде раскрылось числовое исключение.

person register    schedule 25.03.2011