2010-12-03 5 views
4

Я хочу проверить, имеет ли 32-разрядное число IEEE754 значение точно 0.0f (время от времени оно будет установлено на него). Ошибки накопления будут равны нулю, поскольку данные будут часто обновляться от датчика. Мой процессор не имеет аппаратного FPU, поэтому операции выполняются в довольно быстрой библиотеке программного обеспечения. Тем не менее, это все еще сотни циклов для таких вещей, как добавление, вычитание и сравнение.Сравните число с плавающей запятой до нуля

Так мне было интересно, почему мой компилятор делает это:

240:     if(p_viewer->roll != 0.0f) 
03FBC B81160  mul.uu w2,#0,w2 
03FBE 900A2E  mov.w [w14+20],w4 
03FC0 900064  mov.w [w4+12],w0 
03FC2 9000F4  mov.w [w4+14],w1 
03FC4 07E91F  rcall __nesf2 
03FC6 E00000  cp0.w w0 
03FC8 320054  bra z, 0x004072 

__nesf2, по-видимому сравнивает два числа с плавающей точкой. Почему он не просто сравнивает с 0.0f в целочисленной форме, то есть 0x00000000? Есть ли причина, по которой это не так, или это просто упущенная возможность оптимизации?

Мой компилятор - MPLAB C30, версия GCC v3.23.

ответ

7

Потому что -0.0f также сравнивается с 0.0f, как того требует стандарт IEEE-754.

Вы можете заменить вызов сравнением с целыми представлениями как -0 (0x80000000) и +0, если это серьезная проблема с производительностью. (Или, еще лучше, замаскируйте бит знака и сравните его с 0.0f).

+1

Я задавался вопросом, почему компилятор не сделал этого, вероятно, было бы только 10 циклов максимум, в то время как функции __nesf2 занимает около 100 циклов. – 2010-12-03 20:40:53

+1

Отсутствие проблемы с сигнализацией NaN, это просто пропущенная оптимизация. Введите ошибку. – 2010-12-03 20:45:06

+0

И учитывая возраст компилятора (gcc 3.2.3?), Вполне вероятно, что (а) у него много пропущенных оптимизаций и (б) никто не заинтересован в его исправлении. – 2010-12-03 21:35:36

1

Если это реализация с плавающей точкой IEEE, она должна учитывать сигнализацию NAN.

Возможно, вам это неинтересно, но компилятор этого не знает.

1

Это упущенная возможность оптимизации. 0.f - частный случай, так как он должен сравнивать с -0.f и 0.f. Но все же это было бы быстрее сравнить как ints.

Почему это не оптимизировано? Я бы сказал, что это проблема интеграции. Подобные вещи обычно падают между стульями. Люди, у которых есть задача собрать SDK платформы, выбрать компилятор (gcc), библиотеку программного обеспечения с плавающей запятой и удастся склеить ее вместе наилучшим образом. В общем случае это работает нормально, и для улучшения мало стимулов, так как поплавки программного обеспечения, как правило, слишком медленны. Худшая часть - это не сравнение, а все остальное.

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

0

Для проверки на 0.0f вам не нужно IEEE вещи, как:

int isFloatNull(float f) 
{ 
    static float i; 
    return !memcmp(&i,&f,sizeof i); 
} 
Смежные вопросы