|
Проверка float на "численность", как проверить, что float не "nan"? |
|
|
|
Feb 3 2009, 10:39
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Сейчас встретил в программе кусок Код sprintf(str, "%f", fCNa); if(isalpha(str[1]))fCNa = 0; Я так подозреваю, что это проверка fCNa на допустимость (или как там по-русски сказать) Если это так, то решение, по-моему, слишком избыточное, учитывая что *printf() нигде больше не используется Какие могут быть другие способы, менее затратные?
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 17)
|
Feb 3 2009, 11:36
|

Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328

|
Цитата(MrYuran @ Feb 3 2009, 17:39)  Какие могут быть другие способы, менее затратные? Я пользуюсь таким кодом: CODE //****************************************************************************** // 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)); }
Причина редактирования: Для уменьшения видимого размера цитаты исходника тэги code заменены на codebox.
|
|
|
|
|
Feb 3 2009, 11:53
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(shreck @ Feb 3 2009, 14:36)  Я пользуюсь таким кодом: ... uint32 *pval = reinterpret_cast<uint32*>(&val); ... Спасибо, а вот это reinterpret_cast<uint32*> - на каком языке написано? я так подозреваю, на си это что-то типа (uint32*)?
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 3 2009, 12:14
|
Местный
  
Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233

|
Цитата(MrYuran @ Feb 3 2009, 13:53)  reinterpret_cast<uint32*> - на каком языке написано? я так подозреваю, на си это что-то типа (uint32*)? C++ Правильно подозреваете. Цитата(shreck @ Feb 3 2009, 13:36)  ... Все уже придумано до нас  Код #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(); }
|
|
|
|
|
Feb 3 2009, 12:50
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(vik0 @ Feb 3 2009, 14:14)  Все уже придумано до нас  Действительно, придумано. Код #include <math.h> // Проверка значения float на корректность. bool is_correct_float(float val) { return !isnan(val); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 3 2009, 13:04
|
Местный
  
Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233

|
Цитата(Сергей Борщ @ Feb 3 2009, 14:50)  А как быть с +/-INF ?
|
|
|
|
|
Feb 3 2009, 13:46
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(vik0 @ Feb 3 2009, 15:04)  А как быть с +/-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). Цитата(MrYuran @ Feb 3 2009, 15:30)  В общем, всем спасибо, сделал misc.c как у shreсk'a, только на си. Ошибочное решение. Представление плавающей точки - компиляторо- и процессорозависимо. Вы закладываететсь на конкретную реализацию, теряя портабельность. Разработчики компиляторов предоставляют стандартные макросы для этих операций - isnan() isinf() и кучу других. Если вас не устраивает их встраивание - сделайте обертки, но не закладывайтесь на конкретное представление чисел компилятором.
Сообщение отредактировал Сергей Борщ - Feb 3 2009, 13:51
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 3 2009, 13:55
|
Местный
  
Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233

|
Цитата(Сергей Борщ @ Feb 3 2009, 15:46)  inf - это тоже not a number, и, значит, должен отсекаться по isnan(). Беглая проверка показала что MSVC++2008 так не считает. Цитата Лезть в стандарт? Гляньте, если не затруднит. Хочется прояснить для себя этот вопрос.
|
|
|
|
|
Feb 4 2009, 03:40
|

Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328

|
Цитата(Сергей Борщ @ Feb 3 2009, 20:46)  Ошибочное решение. Представление плавающей точки - компиляторо- и процессорозависимо. Вы закладываететсь на конкретную реализацию, теряя портабельность. Разработчики компиляторов предоставляют стандартные макросы для этих операций - isnan() isinf() и кучу других. Если вас не устраивает их встраивание - сделайте обертки, но не закладывайтесь на конкретное представление чисел компилятором. Полностью поддерживаю. Но... 1. Не у всех компиляторов стандартная библиотека содержит указанные функции, например, в IARMSP342 я их не нашел. 2. Если документация к компилятору утверждает, что он поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый. 3. Человеку нужно решение на С.
|
|
|
|
|
Feb 4 2009, 06:46
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(shreck @ Feb 4 2009, 05:40)  1. Не у всех компиляторов стандартная библиотека содержит указанные функции, например, в IARMSP342 я их не нашел. Тут возразить нечего... Разве что можно предложить дать этим функциям стандартные названия, чтобы при компиляции компилятором, который имеет такие функции, получить ошибку и заменить их на библиотечные. Цитата(shreck @ Feb 4 2009, 05:40)  2. Если документация к компилятору утверждает, что он поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый. А как же большие и маленькие индейцы? Затык именно в попытке обращаться к участку памяти как к длинному целому. К тому же, в зависимости от реализации компилятора, и float и double могут иметь непредсказуемое число бит. Цитата(shreck @ Feb 4 2009, 05:40)  3. Человеку нужно решение на С. Вызов описанного в стандарте языка макроса стандартной библиотеки - самое что ни на есть "решение на С".
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 4 2009, 07:12
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Извиняюсь за занудство... CODE /* - MATH.H -
The ANSI-defined (+ a few additional) mathematical functions.
$Revision: 1.4 $
Copyright 1986 - 1999 IAR Systems. All rights reserved. */
#ifndef _MATH_INCLUDED #define _MATH_INCLUDED
#ifndef _SYSTEM_BUILD #pragma system_include #endif
#include "sysmac.h"
#ifndef HUGE_VAL #if __FLOAT_SIZE__ == __DOUBLE_SIZE__ #define HUGE_VAL 3.402823466e+38 #else #define HUGE_VAL 1.7976931348623158e+308 #endif #endif
/* What is returned if a domain error occurred */ #define __EDOM_VALUE HUGE_VAL
/* PI, PI/2, PI/4, 1/PI, 2/PI */ #define __PI 3.141592653589793238462643 #define __PIO2 1.570796326794896619231 #define __PIO4 .785398163397448309615 #define __INVPI 0.31830988618379067154 #define __TWOOPI 0.63661977236758134308
/* SQRT(2), SQRT(2) + 1, SQRT(2) - 1,SQRT(2) / 2 */ #define __SQRT2 1.4142135623730950488016887 #define __SQ2P1 2.414213562373095048802 #define __SQ2M1 .414213562373095048802 #define __SQRTO2 0.707106781186547524
/* LN(10), TWO-LOG(e), LN(2) e */ #define __LN10 2.302585092994045684 #define __LOG2E 1.4426950408889634073599247 #define __LOG2 0.693147180559945309417232 #define __E 2.718281828459045235360287
#if __IAR_SYSTEMS_ICC__ < 2 #if __TID__ & 0x8000 #pragma function=intrinsic(0) #endif #endif
#ifndef MEMORY_ATTRIBUTE #define MEMORY_ATTRIBUTE #endif
__INTRINSIC MEMORY_ATTRIBUTE double atan(double);
__INTRINSIC MEMORY_ATTRIBUTE double atan2(double, double);
__INTRINSIC MEMORY_ATTRIBUTE double cos(double);
__INTRINSIC MEMORY_ATTRIBUTE double cosh(double);
__INTRINSIC MEMORY_ATTRIBUTE double fabs(double);
__INTRINSIC MEMORY_ATTRIBUTE double fmod(double, double);
__INTRINSIC MEMORY_ATTRIBUTE double exp(double);
__INTRINSIC MEMORY_ATTRIBUTE double ldexp(double, int);
__INTRINSIC MEMORY_ATTRIBUTE double log(double);
__INTRINSIC MEMORY_ATTRIBUTE double log10(double);
__INTRINSIC MEMORY_ATTRIBUTE double modf(double, double *);
__INTRINSIC MEMORY_ATTRIBUTE double pow(double , double);
__INTRINSIC MEMORY_ATTRIBUTE double sin(double);
__INTRINSIC MEMORY_ATTRIBUTE double sinh(double);
__INTRINSIC MEMORY_ATTRIBUTE double sqrt(double);
__INTRINSIC MEMORY_ATTRIBUTE double tan(double);
__INTRINSIC MEMORY_ATTRIBUTE double tanh(double);
__INTRINSIC MEMORY_ATTRIBUTE double floor(double);
__INTRINSIC MEMORY_ATTRIBUTE double ceil(double);
__INTRINSIC MEMORY_ATTRIBUTE double frexp(double, int *);
__INTRINSIC MEMORY_ATTRIBUTE double acos(double);
__INTRINSIC MEMORY_ATTRIBUTE double asin(double);
#if __IAR_SYSTEMS_ICC__ < 2 #if __TID__ & 0x8000 #pragma function=default #endif #endif
#endif /* _MATH_INCLUDED */
Вот так... это ИАР для MSP чё-то не находит он в math.h isnan(), isfinite() etc... Может, где-то в другом месте прописано, искать лень... В общем, всем спасибо и респект, портирование в ближайшие годы не предполагается, MSP rulez (особенно для портативных приложений) Пока оставляю как есть. Тем более что в тексте и так полно ручных крякозяблей, типа юниона float с char'ами, с последующей мануальной терапией... А поскольку проект в целом рабочий и серия насчитывает несколько сотен экз. за 2 года, логично "не лечить то, что работает", просто где явно можно что-то улучшить, слегка подпиливаю.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 4 2009, 07:34
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(MrYuran @ Feb 4 2009, 09:12)  Вот так... это ИАР для MSP чё-то не находит он в math.h isnan(), isfinite() etc... У меня аналогичный файл в CLIB от версии 3.21А. Там и stdint.h нет и много еще чего полезного. А в math.h от DLIB - все есть. Так что выберите библиотеку DLIB в настройках проекта - и будет все хорошо.
Причина редактирования: Уменьшение цитаты.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|