LINUX.ORG.RU

Быстрая проверка float range на C


1

2

Привет всем, вопрос просто по теории, допустим у меня есть

float a = 1.0f;
float min = 20.0f;
float max = 100.221f
bool in_range = ((min <= a) && (a <= max));
А есть ли еще быстрые способы проверки нахождения числа в диапазоне?


Ответ на: комментарий от ddos3

сколько в последнее время развелось самоуверенных недоучек.

ну я рад за тебя, что ты теперь вполне учёный.

По теме: да, тут я похоже ошибся.

emulek
()
Ответ на: комментарий от emulek

И где там написано, что оператор && должен быть ленивым?

а он не ленивый разве?

И где там написано, что оператор && должен быть ленивым? Это просто оптимизация, из бородатых годов. Никто не мешает посчитать все элементы, ведь побочных эффектов нет. Так можно избавиться от ветвлений.

опять придираешься?

А, ну да. C, C++, разницы же нет.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Никто не мешает посчитать все элементы, ведь побочных эффектов нет. Так можно избавиться от ветвлений.

ну да. Только тебе придётся ещё float → int преобразовать, потом sign сделать, а потом 0 и -1 превратить в true, а 1 в false. А потом этот bool всё равно пойдёт в ветвление.

Кстати, откуда в C bool? Раньше вроде-бы не было?

А, ну да. C, C++, разницы же нет.

в данном случае я про операторы говорил. Вот этот факт и подчеркнул C++ синтаксисом. Как ты наверное знаешь, просто * в C может что угодно значить. А я уточнил, что это оператор умножения целых чисел.

emulek
()
Ответ на: комментарий от Waterlaz

a*(b*c) никогда не будут вычисляться как (a*b)*c

ну а если a*b не меняется в цикле, кто мешает вынести a*b из тела?

emulek
()
Ответ на: комментарий от emulek

Кстати, откуда в C bool? Раньше вроде-бы не было?

Было, было: stdbool.h И что бы совсем обезбашить, то и complex.h до кучи.

beastie ★★★★★
()
Ответ на: комментарий от emulek

Только тебе придётся ещё float → int преобразовать, потом sign сделать, а потом 0 и -1 превратить в true, а 1 в false

Нагородил. Для сравнения есть соответствующие инструкции, можно даже делать несколько сравнений за раз. А вот про инструкцию sign, возвращающую -1, 0 или 1, я в первый раз слышу. У тебя какие-то особенные x86?

А потом этот bool всё равно пойдёт в ветвление.

И будет одно ветвление вместо двух. Что уже хорошо.

в данном случае я про операторы говорил.

А, да, вспомнил. Как ты там любишь говорить? «По моей терминологии».

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Придирка к словам — AVX же есть некое логическое продолжение SSE, шестая нога (я мог сбиться со счета) у собаки по имени x86.

buddhist ★★★★★
()
float a = 1.0f;
float min = 20.0f;
float max = 100.221f
float c=(max-min)/2;
float l=max-c;

bool in_range = (abs(a-c)<=l));

ne znau bystree li.

dikiy ★★☆☆☆
()
Ответ на: комментарий от buddhist

Есть у психологов какой-то тест, там в одном из вопросов показывают два прямоугольника, один вытянутый вертикально, другой горизонтально. И спрашивается — одинаковые ли фигуры. Как выясняется, у каждого человека — своя граница похожести. Кто-то считает фигуры одинаковыми, ведь они совпадут, если первую повернуть. Кто-то утверждает, что одна вертикальная, а другая горизонтальная, и потому они разные.

i-rinat ★★★★★
()

Раз тут два вычетания, то можно попробовать векторизовать

NeXTSTEP ★★
()
Ответ на: комментарий от i-rinat

У тебя какие-то особенные x86?

я не про x86, я в общем случае. В x86 на регистрах можно вычесть из регистра его же с учётом переноса. Получится 0 или ~0. В векторных инструкциях не помню.

И будет одно ветвление вместо двух. Что уже хорошо.

в теории можно вообще отказаться от ветвлений, если наша цель — отфильтровать те числа, которые (не) в диапазоне. А остальные поменять на что-то другое. Я просто не понимаю, зачем ещё в int переделывать? Скорости это явно не добавит.

в данном случае я про операторы говорил.

А, да, вспомнил. Как ты там любишь говорить? «По моей терминологии».

вот именно. А то ты скажешь, что * это разименовывание указателя (:

emulek
()
Ответ на: комментарий от i-rinat

я говорил о том, что все давно используют SIMD расширения, которые начиная с третьего пня умеют float(просто SSE). Потому нет смысла дёргать float→int. Ты мою мысль только подтвердил.

Остальное — твоя демагогия.

emulek
()
Ответ на: комментарий от emulek

Я просто не понимаю, зачем ещё в int переделывать? Скорости это явно не добавит.

Студент и преподаватель.
П: Кто написал это произведение?
С: Прокофьев.
П: Рахманинов.
С: Да, Рахманинов. А причём тут Прокофьев?

Сам бреда нанесёшь, а потом на других свои слова развешиваешь.

i-rinat ★★★★★
()
Ответ на: комментарий от emulek

Твою жопу постоянно спасают модераторы с такой же пробитой мною жопой, но всё же.

я говорил о том, что все давно используют SIMD расширения, которые начиная с третьего пня умеют float(просто SSE).

Нет, балаболка - я уже тебе говорил про: -mfpmath. Его юзает для amd64 гцц по дефолту не потому, что «фпу пропало», а просто форфан. Он не умеет детектить нормально когда надо, а когда не надо юзать «фпу».

-mfpmath=sse и -mfpmath=387 сравнялись недавно, в донехалемские времена с ними была жопа и sse крайне тормазил. Поэтому почти всегда от -mfpmath=sse толку было мало и 387 давал профит.

Дефолтное принятие связанно с регистрами фпу/sse, которые входят в amd64 call abi. И передаёются аргументы через sse-проекцию. И чтобы не замарачиватся и не рвать жопу со всей фигнёй - проще везде юзать sse.

При складывании аргументов в стек(как в 32битном callabi) - там покласть куда их доставать.

Потому нет смысла дёргать float→int.

Твой балаболинг противоречит сам себе. Ты понимаешь что такое каст? Есть 2типа «кастов» - это: а) каст типа - т.е. представления числа и б) каст обработчика этого представления без смены представления. Вообще поидее кастом называется только пункт а.

В х86 есть «алу» и фпу. У фпу свои регистры и в алушнофпушном коде нужна миграция данных в любом из кастов, т.е. если ты кастуешь (int)7.f и *(int *)&7.f - это две абсалютно разные конструкции, но миграция данных алу-фпу происходит всегда.

В sse(х86 симдах) же регистры общие и миграция между регистрами 2-х разных «Блоков» не нужна.

Какбэ есть movss и movps, но они ничем не отличаются - это просто алиасы для обычного мува. И код вида:

float a, b;// обычный мув в какой-то xmm-регистр х2.
(a > b)//пример 1
(*(int *)&a > *(int *)&b)//пример 2

Эти два примера ничем не отличаются - тут небудет никаких кастов - в них будет тотже самый cmp, разница лишь в том, что в первом случае будет вызвана его модификация для float, а во втором для int.

anonymous
()
Ответ на: комментарий от beastie

дык при чём тут ТИП bool?

Standard C (since C99) and several dialects of C such as Objective-C provide definitions of a Boolean type as an integer type and macros for «false» and «true» as 0 and 1, respectively. Thus logical values can be stored in integer variables, and used anywhere integers would be valid, including in indexing, arithmetic, parsing, and formatting. This approach («Boolean values are just integers») has been retained in all later versions of C.

http://en.wikipedia.org/wiki/Boolean_datatype#C.2C_C.2B.2B.2C_Objective-C.2C_...

emulek
()
Ответ на: комментарий от anonymous

Эти два примера ничем не отличаются - тут небудет никаких кастов - в них будет тотже самый cmp, разница лишь в том, что в первом случае будет вызвана его модификация для float, а во втором для int.

тут кастов не будет, ту будет неправильно сравнение для другого типа. Для правильного сравнения нужен каст.

emulek
()
Ответ на: комментарий от emulek

это поможет от антипереполнения

Да кого волнует андерфлоу? У флоата проблема другая - короткая мантисса, ~8 разрядов. Из-за этого даже на сравнительно ровном месте может набежать нехилая погрешность и никакие домножения от этого не спасают.

no-such-file ★★★★★
()
Ответ на: комментарий от emulek

Ну загляни уже в саму "шапку", а?

typedef bool есть? Есть. Стандартом определён? Да. В GCC и PCC это встроенный тип? Да.

Так о чём мы вообще спорим? ;)

beastie ★★★★★
()
Ответ на: комментарий от no-such-file

Да кого волнует андерфлоу? У флоата проблема другая - короткая мантисса

порядок там тоже всего 8 бит. 10¯²⁰*10¯²⁰=10¯⁴⁰=0. И всё.

Проблема как раз в порядке, ибо числа после операций нормализуются, и всегда 0<m<1. Ну да, 1000+0.0001=1000. Но это не очень плохо(если потому из этого результата 1000 не вычитать. А вычитать близкие числа вообще вредно).

Порядок в отличие от мантиссы не нормализуется. Некуда. Потому умножение/деление часто приводит к проблемам деления на ноль и прочей ☣.

emulek
()
Ответ на: комментарий от beastie

Ну загляни уже в саму «шапку», а?

это не стандарт.

Стандартом определён?

нет под рукой.

В GCC и PCC это встроенный тип?

там много чего нестандартного. ЕМНИП там _Bool вроде был. Который typdef'нут на int.

Так о чём мы вообще спорим?

я не спорю, я просто как-то столкнулся с отсутствием bool, и наличием true/false(в stdbool.h). Сейчас вспомнил, и пытаюсь прояснить вопрос.

emulek
()
Ответ на: комментарий от emulek

Рили, думаешь? sse? Где?

ну а там я что-то ABS не нашёл

А ты и не искал. andps. Зачем нужен абс, если это делает за and?

Вот и думаю, как твой код разложить по феншую...

Слишком анскилен, куда разложить?

anonymous
()
Ответ на: комментарий от anonymous

А ты и не искал. andps. Зачем нужен абс, если это делает за and?

тупо знак сбросить предлагаешь?

Слишком анскилен, куда разложить?

вот и прошу помощи у самого царя.

emulek
()

А есть ли еще быстрые способы проверки нахождения числа в диапазоне?

а куда быстрее-то ?

хотя..это оптимизируется исходя совместно с окружающим кодом, из свойств «а» (из распределения, мат.ожидания и т.д.) и пачки других предпосылок..

ваш пример вырожденный, но например если min,max известны во время компиляции, размер диапазона достаточно велик, «а» равномерно распределено по всему диапазону float:

#if (max-min>0)
#define IN_RANGE(a) (min<=(a) && (a)<=max)
#else
#define IN_RANGE(a) ((a)<=max && min<=(a))
#endif

принцип в том, что && ленив и второе сравнение не производится если первое false. Задача в том чтобы преобразовать выражение так чтобы первое-же сравнение отсекало как можно большую часть.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

а куда быстрее-то ?

Есть куда, сама задача является говном по определению, которая даже на 10% не претендует и вообще не имеет смысла.

Юзать IN_RANGE на каждую чисилку - это такой 70-й год. Проблема не в IN_RANGE, а в том как это заюзать и потомо бработать его юз не скатившись в убогое sisd-мышление.

Твоя оптимизация не имеет особо смысла, ибо последующие выражения не зависимы. Заменив && на & - ты ничего не потеряешь. А в симдах вообще вменяемый человек не заюзает эти нищее операторы, ибо какбэ только через жопу.

anonymous
()
Ответ на: комментарий от emulek

тупо знак сбросить предлагаешь?

Не какбэ abs() это и делает, либо я не прав?

вот и прошу помощи у самого царя.

А эта задача не имеет смысла.

Все жопу рвут не о том, как сделать IN_RANGE() быстрее, ибо это примитивщина, а как наиболее дешево заюзать его выхлоп.

Т.е. надо придумать что-то луше:

do {
  if(inrange(*dataset)) work(dataset);
} while(++dataset != end);

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

anonymous
()
Ответ на: комментарий от anonymous

Есть куда, сама задача является говном по определению, которая даже на 10% не претендует и вообще не имеет смысла.

Юзать IN_RANGE на каждую чисилку - это такой 70-й год. Проблема не в IN_RANGE, а в том как это заюзать и потомо бработать его юз не скатившись в убогое sisd-мышление.

Твоя оптимизация не имеет особо смысла, ибо последующие выражения не зависимы. Заменив && на & - ты ничего не потеряешь. А в симдах вообще вменяемый человек не заюзает эти нищее операторы, ибо какбэ только через жопу.

ты бы это, закусывал что-ли..

MKuznetsov ★★★★★
()
Ответ на: комментарий от anonymous

Не какбэ abs() это и делает, либо я не прав?

прав.

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

соглашусь. Хотя всё от задачи зависит.

Можно данные сразу по корзинам распихать, часто 80% лежат в 20% корзин. Тогда в 80% случаев мы точно узнаем результат за O(1), а в 20% будем считать в N раз быстрее.

emulek
()
Ответ на: комментарий от MKuznetsov

ты бы это, закусывал что-ли..

не, зерно разума в его рассуждениях есть. Только с ЧСВ проблема, и в отсутствии самокритики. На то он и Царь.

emulek
()
Ответ на: комментарий от MKuznetsov

Ты со мною не согласен? Ну давай поспорим, хотя явно видно, что ты зассал, но всё же - попытайся.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.