Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как определить что float имеет не цифровое значение (NaN)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
LeshaL
В __eeprom обьявлена переменная типа float. Как с минимальными затратами определить, что эта переменная имеет нечисловой формат (когда по адресу хранения float появляется значение 0xFFFFFFFF) чтобы привести ее в какое-нибудь начальное значение числового формата? Операции сравнения не работают. Если я пытаюсь определить нечисловой формат так:
if(my_float==0.NaN),
то, судя по ассемблерному тексту, my_float сравнивается не с 0xFFFFFFFF, a c 0x7FFFFFFF. Если сравниваю так: if(my_float==-0.NaN), то ничего не меняется...
Виктория
Можно так попробовать
if ((*(unsigned long *)(&my_float)) == 0xffffffffL)

а 0x7fffffff - это тоже спец. значение, не float, поэтому в чем то компилер прав. Могу поискать описание этих спец.значений.
LeshaL
Цитата(Vic1 @ Mar 13 2006, 16:54) *
Можно так попробовать
if ((*(unsigned long *)(&my_float)) == 0xffffffffL)

а 0x7fffffff - это тоже спец. значение, не float, поэтому в чем то компилер прав. Могу поискать описание этих спец.значений.


Пробовал и так. В этом случае компилятор работает только с указателем на переменную, без ее непосредственного извлечения из eeprom, т.е. без вызова функции __eeget32_16. Если только делать это через промежуточную переменную в ОЗУ, но при десятках переменных в разных частях программы получается не очень красиво...
starter48
Цитата(LeshaL @ Mar 13 2006, 17:03) *
В __eeprom обьявлена переменная типа float. Как с минимальными затратами определить, что эта переменная имеет нечисловой формат (когда по адресу хранения float появляется значение 0xFFFFFFFF) чтобы привести ее в какое-нибудь начальное значение числового формата? Операции сравнения не работают. Если я пытаюсь определить нечисловой формат так:
if(my_float==0.NaN),
то, судя по ассемблерному тексту, my_float сравнивается не с 0xFFFFFFFF, a c 0x7FFFFFFF. Если сравниваю так: if(my_float==-0.NaN), то ничего не меняется...

я делал так (в IAR 3.20):
Код
static char is_nan(const float *F)
{
  return ((((unsigned char*)F)[2] & 0x80)==0x80) && ((((unsigned char*)F)[3] & 0x7F)==0x7F);
}

Этой ф-ии передаю указатель на float в RAM.
Но эта ф-я зависит от порядка байт во float, этот вариант для IAR320 для AVR.
Измени её под свои требования.
LeshaL
Цитата(starter48 @ Mar 13 2006, 18:31) *
Цитата(LeshaL @ Mar 13 2006, 17:03) *

В __eeprom обьявлена переменная типа float. Как с минимальными затратами определить, что эта переменная имеет нечисловой формат (когда по адресу хранения float появляется значение 0xFFFFFFFF) чтобы привести ее в какое-нибудь начальное значение числового формата? Операции сравнения не работают. Если я пытаюсь определить нечисловой формат так:
if(my_float==0.NaN),
то, судя по ассемблерному тексту, my_float сравнивается не с 0xFFFFFFFF, a c 0x7FFFFFFF. Если сравниваю так: if(my_float==-0.NaN), то ничего не меняется...

я делал так (в IAR 3.20):
Код
static char is_nan(const float *F)
{
  return ((((unsigned char*)F)[2] & 0x80)==0x80) && ((((unsigned char*)F)[3] & 0x7F)==0x7F);
}

Этой ф-ии передаю указатель на float в RAM.
Но эта ф-я зависит от порядка байт во float, этот вариант для IAR320 для AVR.
Измени её под свои требования.


В том то и дело, что передается указатель на float в RAM, а мне нужно проверить float во внутреннем eeprom. Каждый раз организовывать промежуточную переменную типа float только лишь для проверки валидности данных типа float в eeprom в разных кусках программы как-то коряво. Неужели нет более простого пути? Красиво работает if(my_float==0.NaN), но проверяет только на 0x7FFFFFFF, а в eeprom, сами понимаете, чаще может быть значение 0xFFFFFFFF.
starter48
Цитата(LeshaL @ Mar 13 2006, 21:03) *
Цитата(starter48 @ Mar 13 2006, 18:31) *

я делал так (в IAR 3.20):
Код
static char is_nan(const float *F)
{
  return ((((unsigned char*)F)[2] & 0x80)==0x80) && ((((unsigned char*)F)[3] & 0x7F)==0x7F);
}

Этой ф-ии передаю указатель на float в RAM.
Но эта ф-я зависит от порядка байт во float, этот вариант для IAR320 для AVR.
Измени её под свои требования.


В том то и дело, что передается указатель на float в RAM, а мне нужно проверить float во внутреннем eeprom. Каждый раз организовывать промежуточную переменную типа float только лишь для проверки валидности данных типа float в eeprom в разных кусках программы как-то коряво. Неужели нет более простого пути?

Я тебе дал идею как распознать NaN. Переделай эту ф-ю для работаы с EEPROM.
Создавать отдельную переменную для этого совсем не обязательно.
Можешь использовать указатель на float в eeprom.
Пример (на железе не проверял):
Код
static unsigned char readEEPROM(unsigned char __eeprom *addr)
{
  while(EECR&(1<<EEWE));//wait for EEWE -> 0
  EEAR=(unsigned short)addr;
  EECR|=(1<<EERE);//master read
  EEAR=0;//to prevent EEPROM corruption
  return EEDR;
}

static char is_nan(const float __eeprom *F)
{
  return ((readEEPROM((unsigned char __eeprom*)F + 2) & 0x80)==0x80) &&
    ((readEEPROM((unsigned char __eeprom*)F + 3) & 0x7F)==0x7F);
}

Цитата(LeshaL @ Mar 13 2006, 21:03) *
Красиво работает if(my_float==0.NaN), но проверяет только на 0x7FFFFFFF, а в eeprom, сами понимаете, чаще может быть значение 0xFFFFFFFF.

Это не корректно, т.к. NaN - это не только 0x7FFFFFFF.
Т.е. тестировать на NaN через сравнение с константой некорректно.
Виктория
Цитата
Цитата
Красиво работает if(my_float==0.NaN), но проверяет только на 0x7FFFFFFF, а в eeprom, сами понимаете, чаще может быть значение 0xFFFFFFFF.


Это не корректно, т.к. NaN - это не только 0x7FFFFFFF.
Т.е. тестировать на NaN через сравнение с константой некорректно.


Некорректность еще и в том, что результат операции сравнения float-оператора с НЕ-числом (это Ваша спец. константа) не дает правильного результата (для этого, т.е. грамотного управления вычислениями эти спец.константы и были введены в соотв. стандарт IEEE). Подробнее все в стандарте и можно посмотреть.
Еще один посыл. Так как сравнение float-чисел выполняется с помощью специальной библиотечной функции, то и сравнение float c NaN необходимо делать аналогично - т.е. с помощью своей функции. Starter48 прав! Можно и на асме эту функцию написать, если захотите большей эффективности.
З.Ы.: а NaN все-таки лучше не допускать в своих алгоритмах, эти константы были введены в стандарт для отладки программ, реализующих численные алгоритмы.
LeshaL
Удивительно, что в ИАРе не оказалось встроенной функции isnan, как в других компиляторах, в том числе и для АВР.
Вообщем, собрав мнение коллективного разума сделал то что хотел с минимальными затратами:

unsigned char isnan(float x)
{
return (((*(unsigned long *)(&x))&0x7F800000)==0x7F800000);
}

Всем спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.