2015-09-23 2 views
10

std::exp Возвращает -infinity при использовании представления float бесконечности и построения двоичного кода x64 с использованием Visual C++ 2013. Я бы ожидал, return 0, что происходит с сборками Win32 или с версией std::exp, которая занимает double.std :: exp of float отрицательная бесконечность возвращает отрицательную бесконечность для x64 сборок в Visual C++ 2013

Этот код, построенный как x64, демонстрирует проблему.

#include <limits> 
#include <iostream> 

int main(const int argc, const char** argv) { 
    std::cout << "exp of float -infinity: " << std::exp(-std::numeric_limits<float>::infinity()) << std::endl; 
    std::cout << "exp of double -infinity: " << std::exp(-std::numeric_limits<double>::infinity()) << std::endl; 
} 

Параметры командной строки для компиляции (из Visual Studio):

/GS /Wall /Gy /Zc:wchar_t /Zi /Gm- /Od /sdl /Fd"x64\Release\vc120.pdb" /fp:precise /D "_MBCS" /errorReport:prompt /WX /Zc:forScope /Gd /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\NumericLimitsTest.pch" 

Выход выше:

exp of float -infinity: -1.#INF 
exp of double -infinity: 0 

Почему это происходит?

+2

Это ошибка; он исправлен в библиотеках времени исполнения Visual C++ 2015. –

+0

@JamesMcNellis - разве это не окончательный ответ? –

ответ

8

Я бы сказал, что это было ошибкой какого-либо описания, поскольку C++ 11 отзывается на C99 для функции cmath, и C99 четко заявляет в F.9.3.1, что exp(−∞) returns +0. Однако имейте в виду, что это приложение в стандарте, которое гласит:

Реализация, которая определяет __STDC_IEC_559__, должна соответствовать спецификациям в этом приложении.

Этот макрос не по всей видимости, определяется либо в 32- или 64-битном режиме в MSVC, так что, вероятно, не ошибка, и вы можете быть не повезло. Также изменение режима с плавающей запятой между /fp:strict и /fp:precise не делает ничего лучше.

Во всех случаях результат, похоже, отличается от 32-битной и 64-битной цели и, основываясь на стандарте, который только утверждает, что будет compute the base-e exponential of x, по-видимому, не требуется, как, похоже, все в порядке.


Если вы после того, как быстро исправить, используя функцию pow, кажется, генерировать правильные результаты:

#define DBL_E 2.71828182845904523536 
#define FLT_E 2.71828182845904523536f 
std::cout 
    << "exp of float -infinity: " 
    << std::pow(FLT_E, -std::numeric_limits<float>::infinity()) 
    << std::endl; 
std::cout 
    << "exp of double -infinity: " 
    << std::pow(DBL_E,-std::numeric_limits<double>::infinity()) 
    << std::endl; 

Это создает ноль для обеих линий независимо от того, есть ли у вас 64-bit/32-bit, debug/release или fp:precise/fp:strict но я не могу сказать, гарантировано ли это.

+1

Не все ли дополнительные приложения F? – hvd

+0

@hvd, зависит от того, определяет ли MSVC '_ _STDC_IEC_559_ _'. Я не устанавливаю его локально, поэтому не могу проверить. Я обновлю ответ. – paxdiablo

+0

оценка ++ это действительно может быть строгой/точной проблемой. – imallett

Смежные вопросы