Как объявить математические функции IEEE, такие как ilogbf в MSVC ++ 6? - PullRequest
0 голосов
/ 13 ноября 2009

Может кто-нибудь помочь и подсказать, как включить математические функции IEEE в MSVC ++ 6? Я пробовал оба и, но я все еще получаю эти ошибки:

ошибка C2065: 'ilogbf': необъявленный идентификатор

ошибка C2065: 'scalbnf': необъявленный идентификатор

Ответы [ 3 ]

2 голосов
/ 14 ноября 2009

Это функции C99, а не IEEE754-1985. Microsoft, похоже, решила, что их рынок не заботится о поддержке C99, поэтому они не удосужились предоставить их. Это позор, но если многие из вас (разработчиков) не будут жаловаться, нет никаких оснований ожидать, что ситуация изменится.

Новый стандарт 754, IEEE754-2008, требует этих функций (пункт 5.3.3, «операции logBFormat»), но эта версия стандарта не будет широко принята в течение еще нескольких лет; Даже если это все-таки получит широкое распространение, Microsoft не считает целесообразным предоставлять эти функции в течение десяти лет, в течение которых они были в C99, поэтому зачем им предлагать их только потому, что они соответствуют стандарту IEEE754?

edit: обратите внимание, что scalb и logb определены в IEEE754-1985 Приложение"Рекомендуемые функции и предикаты", но указанное приложение явно "не является частью" указанного стандарта .

2 голосов
/ 13 ноября 2009

Редактировать 3: Надеюсь, это будет мое последнее редактирование. Я пришел к выводу, что я вообще должным образом не ответил на этот вопрос. Я собираюсь оставить свой ответ на месте как предостерегающий рассказ, и потому что он может иметь некоторую образовательную ценность. Но я понимаю, почему у меня нет нулевых голосов, и на самом деле я собираюсь поднять ответ Энди Росса, потому что я думаю, что он гораздо более актуален (хотя и неполен, по крайней мере, на момент написания). Мне кажется, моя ошибка заключалась в том, чтобы воспринимать определения Man, которые я нашел для ilogbf (), немного поверхностно. Это функция, которая принимает целую часть лога с плавающей точкой, насколько сложно это реализовать? Оказывается, что функция на самом деле представляет собой представление IEEE с плавающей запятой, в частности, экспонентную (в отличие от мантиссы) часть этого представления. Я должен был определенно понять это, прежде чем пытаться ответить на вопрос! Для меня интересным является то, как функция может найти экспонентную часть числа с плавающей точкой, так как я думал, что фундаментальное правило C состоит в том, что числа с плавающей точкой повышаются до удваивающихся значений как часть вызова функции. Но это, конечно, отдельная дискуссия.

--- Конец редактирования 3, начало поучительной истории ---

Небольшое прибегание к гуглу предполагает, что они определены в некоторых разновидностях Unix, но, возможно, не соответствуют ни одному из стандартов Posix или ANSI и поэтому не предоставляются библиотеками MSVC. Если функции не находятся в библиотеке, они не будут объявлены в math.h. Очевидно, что если компилятор не может видеть объявления для этих внешних символов, он не будет счастлив, и вы получите ошибки, подобные тем, которые вы перечислили.

Очевидный обходной путь заключается в создании собственных версий этих функций с использованием математических функций, которые предусмотрены . например,

#include <math.h>

int ilogbf( float f )
{
    double d1 = (double)f;
    double d2 = log(d1);
    int ret = (int)d2;
    return ret;
}

Редактировать: Это не совсем правильно. По-видимому, эта функция должна использовать log для base 2, а не натуральные log, так что возвращаемое значение фактически является двоичным показателем. Он также должен принимать абсолютное значение своего параметра, чтобы он работал и для отрицательных чисел. Я поработаю над улучшенной версией, если вы спросите меня в комментарии, в противном случае мне хочется оставить это в качестве упражнения для читателя: -)

Суть моего ответа, то есть, что ANSI C не требует этой функции и что MSVC не включает ее, по-видимому, правильна.

Редактировать 2: Хорошо, я ослаблен и предоставил улучшенную версию без запроса. Вот оно;

#include <math.h>

int ilogbf( float f )
{
    double d1 = (double)f;
    if( d1 < 0 )
        d1 = -d1;
    double d2 = log(d1) / log(2);  // log2(x) = ln(x)/ln(2)
    int ret = (int)d2;
    return ret;
}
1 голос
/ 13 ноября 2009

Если вы знаете, что находитесь в системе IEEE (и в наши дни это делаете), эти функции не нужны: просто проверяйте биты напрямую, объединяя double с uint64_t. Предположительно, вы в первую очередь используете эти функции в интересах эффективности (в противном случае вы бы использовали более естественные операции, такие как log() или exp()), поэтому потратите немного усилий на согласование вашего кода с представлением с плавающей запятой вероятно стоит.

...