реклама на сайте
подробности

 
 
> Проверка float на "численность", как проверить, что float не "nan"?
MrYuran
сообщение Feb 3 2009, 10:39
Сообщение #1


Беспросветный оптимист
******

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



Сейчас встретил в программе кусок
Код
sprintf(str, "%f", fCNa);
if(isalpha(str[1]))fCNa = 0;

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

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

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


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 17)
Палыч
сообщение Feb 3 2009, 11:24
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(MrYuran @ Feb 3 2009, 13:39) *
Какие могут быть другие способы, менее затратные?
Если это - IEEE754, то "нечисла" (положительная и отрицательная бесконечность, нечисло, неопределённость) имеют в порядке (двоичное представление) все единицы. "Нормальные" числа в порядке содержат по крайней мере один нолик.
Go to the top of the page
 
+Quote Post
shreck
сообщение Feb 3 2009, 11:36
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 3 2009, 11:53
Сообщение #4


Беспросветный оптимист
******

Группа: Свой
Сообщений: 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 =)
Go to the top of the page
 
+Quote Post
vik0
сообщение Feb 3 2009, 12:14
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233



Цитата(MrYuran @ Feb 3 2009, 13:53) *
reinterpret_cast<uint32*> - на каком языке написано?
я так подозреваю, на си это что-то типа (uint32*)?

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

Цитата(shreck @ Feb 3 2009, 13:36) *
...

Все уже придумано до нас smile.gif
Код
#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();
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 3 2009, 12:50
Сообщение #6


Гуру
******

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



Цитата(vik0 @ Feb 3 2009, 14:14) *
Все уже придумано до нас smile.gif
Действительно, придумано.
Код
#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)
Go to the top of the page
 
+Quote Post
vik0
сообщение Feb 3 2009, 13:04
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233



Цитата(Сергей Борщ @ Feb 3 2009, 14:50) *

А как быть с +/-INF ?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 3 2009, 13:30
Сообщение #8


Беспросветный оптимист
******

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



В общем, всем спасибо, сделал misc.c как у shreсk'a, только на си.
Результат - минус 4 кило из сегмента code и увеличение запаса оперативки
Так вот живёшь-живешь, и вдруг - бац, оказывается, float принято на пределы проверять...


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 3 2009, 13:46
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 3 2009, 13:49
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



По-моему, правильно будет использовать isfinite():
Цитата
The isfinite macro determines whether its argument has a finite value (zero,
subnormal, or normal, and not infinite or NaN).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 3 2009, 13:51
Сообщение #11


Гуру
******

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



Цитата(aaarrr @ Feb 3 2009, 15:49) *
По-моему, правильно будет использовать isfinite():
Говорят, у дураков мысли сходятся... Но у умных чаще! smile.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
vik0
сообщение Feb 3 2009, 13:55
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233



Цитата(Сергей Борщ @ Feb 3 2009, 15:46) *
inf - это тоже not a number, и, значит, должен отсекаться по isnan().

Беглая проверка показала что MSVC++2008 так не считает. unsure.gif
Цитата
Лезть в стандарт?

Гляньте, если не затруднит. Хочется прояснить для себя этот вопрос.
Go to the top of the page
 
+Quote Post
shreck
сообщение Feb 4 2009, 03:40
Сообщение #13


Местный
***

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



Цитата(Сергей Борщ @ Feb 3 2009, 20:46) *
Ошибочное решение. Представление плавающей точки - компиляторо- и процессорозависимо. Вы закладываететсь на конкретную реализацию, теряя портабельность. Разработчики компиляторов предоставляют стандартные макросы для этих операций - isnan() isinf() и кучу других. Если вас не устраивает их встраивание - сделайте обертки, но не закладывайтесь на конкретное представление чисел компилятором.

Полностью поддерживаю. Но...
1. Не у всех компиляторов стандартная библиотека содержит указанные функции, например, в IARMSP342 я их не нашел.
2. Если документация к компилятору утверждает, что он поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый.
3. Человеку нужно решение на С.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Feb 4 2009, 06:36
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(shreck @ Feb 4 2009, 06:40) *
... поддерживает для float стандарт IEEE 754, то, рискну предположить, что приведенный мной код не компиляторо- и не процессорозависимый.
В Вашем коде есть одно "тёмное" место - приведение указателя на float к указателю на uint32. Правильность работы Вашего кода будет определятся - как транслятор располагает в памяти байты целых и вещественных чисел. Если - в используемом трансляторе нет стандартной функции определения "нечисла", то, имхо, с этим "тёмным" местом кода можно смириться.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 4 2009, 06:46
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 4 2009, 07:12
Сообщение #16


Беспросветный оптимист
******

Группа: Свой
Сообщений: 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 =)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 4 2009, 07:34
Сообщение #17


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 4 2009, 15:37
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Feb 4 2009, 12:34) *
А в math.h от DLIB - все есть. Так что выберите библиотеку DLIB в настройках проекта - и будет все хорошо.
Угу. Либо DLIB использовать нужно, либо свою функцию написать.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 22:28
Рейтинг@Mail.ru


Страница сгенерированна за 0.01515 секунд с 7
ELECTRONIX ©2004-2016