Конвертация 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, поскольку, хотя он не может определять логическое преобразование, он, вероятно, определяет интегральное преобразование и использование в условном выражении, и я подозреваю, что С++ будет следовать тем же правилам
Ответы
Ответ 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
не является нулевым значением и не сравнивается с равным нулю.