Подтвердить что ты не робот

Конвертация NaN в Bool: True или False?

В какой части спецификации С++ или спецификации float IEEE указано, что значение NaN должно преобразовываться в true в противоположность false?

Если я посмотрю на стандартный раздел С++ 4.12 Boolean Conversions, он говорит:

Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразован в false; любое другое значение преобразуется в значение true.

Теперь поплавки IEEE говорят, что NaN сравнивает false с любым другим значением. Поэтому, является ли NaN истинным или ложным, зависит от того, как вы выполняете сравнение (см. Ниже). Поэтому я предполагаю, что должно быть явное упоминание.

value == 0 ? false : true
value != 0 ? true : false

Теперь, как насчет преобразования в целое число. В приведенной ниже короткой программе показано, что переменная NAN, преобразованная в целое число, приводит к минимальному целому числу, тогда как константа преобразуется в 0 (используя GCC). Это кажется странным.

#include <iostream>
#include <cmath>

void write( double r, int i, bool b )
{
    std::cout << r << " == " <<  i << " == " << (b ? "True" : "False") << std::endl;
}

int main()
{
    double value = NAN;
    write( value, value, value );
    write( NAN, NAN, NAN );
}

Вывод:

nan == -2147483648 == True
nan == 0 == True

Преобразование NaN в ноль, но bool-преобразование как True кажется тревожным. Я также не считаю, что что-то вроде MatLab преобразует NaN в 0 с помощью функции типа int16.

Итак, каковы особенности соответствующих стандартов, которые определяют, как NaN преобразуется в логические и целочисленные значения?

Я также отмечаю C, поскольку, хотя он не может определять логическое преобразование, он, вероятно, определяет интегральное преобразование и использование в условном выражении, и я подозреваю, что С++ будет следовать тем же правилам

4b9b3361

Ответ 1

В C и С++ поведение undefined при преобразовании NAN в целочисленный тип (кроме bool):

C99 6.3.1.4/1: Когда конечное значение реального плавающего типа преобразуется в целочисленный тип, отличный от _Bool, дробная часть отбрасывается (т.е. значение усекается к нулю). Если значение интегральной части не может быть представлено целым типом, поведение undefined.

С++ 11 4.9/1: PRvalue типа с плавающей точкой может быть преобразовано в prvalue целочисленного типа. Преобразование усекает; т.е. дробная часть отбрасывается. Поведение undefined, если усеченное значение не может быть представлено в типе назначения. [Примечание. Если тип назначения bool, см. 4.12. -end note]

В обоих языках преобразование NAN в bool (или _Bool) дает true (или 1):

C99 6.3.1.2/1: когда любое скалярное значение преобразуется в _Bool, результат равен 0, если значение сравнивается с 0; в противном случае результат равен 1.

С++ 11 4.12/1: нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в false; любое другое значение преобразуется в true.

NAN не является нулевым значением и не сравнивается с равным нулю.