Перейти к содержанию
    

Проверка float на "численность"

Сейчас встретил в программе кусок

sprintf(str, "%f", fCNa);
if(isalpha(str[1]))fCNa = 0;

Я так подозреваю, что это проверка fCNa на допустимость

(или как там по-русски сказать)

 

Если это так, то решение, по-моему, слишком избыточное, учитывая что *printf() нигде больше не используется

 

Какие могут быть другие способы, менее затратные?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какие могут быть другие способы, менее затратные?
Если это - IEEE754, то "нечисла" (положительная и отрицательная бесконечность, нечисло, неопределённость) имеют в порядке (двоичное представление) все единицы. "Нормальные" числа в порядке содержат по крайней мере один нолик.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какие могут быть другие способы, менее затратные?

Я пользуюсь таким кодом:

//******************************************************************************
// MISC_CPP
// DESCRIPTION:
// Различного рода вспомагательные функции.
//
//
//******************************************************************************

//------------------------------------------------------------------------------
// T Y P E S	and	D E F I N I T I O N S
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Константa NaN.
const float NaN = 0.0/0.0;

//==============================================================================
// I M P L E M E N T A T I O N
//==============================================================================

//------------------------------------------------------------------------------
// Проверка значения float на число.
bool is_nan(float val)
{
uint32 *pval = reinterpret_cast<uint32*>(&val);
bool result = ((*pval & 0x7F800000)  == 0x7F800000) &&
			  ((*pval & 0x007FFFFF)  != 0x00000000);
return result;
}

//------------------------------------------------------------------------------
// Проверка значения float на бесконечность.
bool is_inf(float val)
{
uint32 *pval = reinterpret_cast<uint32*>(&val);
bool result = ((*pval & 0x7F800000)  == 0x7F800000) &&
			  ((*pval & 0x007FFFFF)  == 0x00000000);
return result;
}

//------------------------------------------------------------------------------
// Проверка значения float на корректность. Не Nan и не Inf.
bool is_correct_float(float val)
{
return !(is_nan(val)||is_inf(val));
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я пользуюсь таким кодом:

...

uint32 *pval = reinterpret_cast<uint32*>(&val);

...

Спасибо, а вот это

reinterpret_cast<uint32*> - на каком языке написано?

я так подозреваю, на си это что-то типа (uint32*)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

reinterpret_cast<uint32*> - на каком языке написано?

я так подозреваю, на си это что-то типа (uint32*)?

C++

Правильно подозреваете.

 

...

Все уже придумано до нас :)

#include <limits>
// Проверка значения float на корректность. Не Nan и не Inf.
bool is_correct_float(float val)
{
    return val != std::numeric_limits<float>::signaling_NaN() && 
      abs(val) != std::numeric_limits<float>::infinity();
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все уже придумано до нас :)
Действительно, придумано.
#include <math.h>
// Проверка значения float на корректность.
bool is_correct_float(float val)
{
    return !isnan(val);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В общем, всем спасибо, сделал misc.c как у shreсk'a, только на си.

Результат - минус 4 кило из сегмента code и увеличение запаса оперативки

Так вот живёшь-живешь, и вдруг - бац, оказывается, float принято на пределы проверять...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как быть с +/-INF ?
Откровенно говоря не силен в плавающей точке, но логика подсказывает, что inf - это тоже not a number, и, значит, должен отсекаться по isnan(). Лезть в стандарт?

Да, полез: это разные классы чисел. Надо использовать isfinite():

The isfinite macro determines whether its argument has a finite value (zero, subnormal, or normal, and not infinite or NaN).

 

 

В общем, всем спасибо, сделал misc.c как у shreсk'a, только на си.
Ошибочное решение. Представление плавающей точки - компиляторо- и процессорозависимо. Вы закладываететсь на конкретную реализацию, теряя портабельность. Разработчики компиляторов предоставляют стандартные макросы для этих операций - isnan() isinf() и кучу других. Если вас не устраивает их встраивание - сделайте обертки, но не закладывайтесь на конкретное представление чисел компилятором.
Изменено пользователем Сергей Борщ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-моему, правильно будет использовать isfinite():

The isfinite macro determines whether its argument has a finite value (zero,

subnormal, or normal, and not infinite or NaN).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-моему, правильно будет использовать isfinite():
Говорят, у дураков мысли сходятся... Но у умных чаще! :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

inf - это тоже not a number, и, значит, должен отсекаться по isnan().

Беглая проверка показала что MSVC++2008 так не считает. :unsure:

Лезть в стандарт?

Гляньте, если не затруднит. Хочется прояснить для себя этот вопрос.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ошибочное решение. Представление плавающей точки - компиляторо- и процессорозависимо. Вы закладываететсь на конкретную реализацию, теряя портабельность. Разработчики компиляторов предоставляют стандартные макросы для этих операций - isnan() isinf() и кучу других. Если вас не устраивает их встраивание - сделайте обертки, но не закладывайтесь на конкретное представление чисел компилятором.

Полностью поддерживаю. Но...

1. Не у всех компиляторов стандартная библиотека содержит указанные функции, например, в IARMSP342 я их не нашел.

2. Если документация к компилятору утверждает, что он поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый.

3. Человеку нужно решение на С.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

... поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый.
В Вашем коде есть одно "тёмное" место - приведение указателя на float к указателю на uint32. Правильность работы Вашего кода будет определятся - как транслятор располагает в памяти байты целых и вещественных чисел. Если - в используемом трансляторе нет стандартной функции определения "нечисла", то, имхо, с этим "тёмным" местом кода можно смириться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Не у всех компиляторов стандартная библиотека содержит указанные функции, например, в IARMSP342 я их не нашел.
Тут возразить нечего... Разве что можно предложить дать этим функциям стандартные названия, чтобы при компиляции компилятором, который имеет такие функции, получить ошибку и заменить их на библиотечные.
2. Если документация к компилятору утверждает, что он поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый.
А как же большие и маленькие индейцы? Затык именно в попытке обращаться к участку памяти как к длинному целому. К тому же, в зависимости от реализации компилятора, и float и double могут иметь непредсказуемое число бит.
3. Человеку нужно решение на С.
Вызов описанного в стандарте языка макроса стандартной библиотеки - самое что ни на есть "решение на С".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...