Здравствуйте, Went, Вы писали:
W>Здравствуйте. Воткнулся в неприятную проблему и не знаю как ее решить хорошо.
W>Есть некое множество каких-то структур, которые нужно отсортировать по значению некоторой функции. Казалось бы все просто — std::sort с предикатом. Но проблема в том, что результат вызова этого предиката приближенный (в силу погрешностей fast floating point model), и иногда начинается дребезг, приводящий к тому, что алгоритм сходит с ума и ругается ассертами (я так понимаю, нарушается транзитивность). Как решить данную проблему, не "городя огород" и не получая лишних накладных расходов?
W>Какие варианты приходят на ум:
W>1. Предрассчитать значение функции. Это хорошо, но его нужно где-то хранить? Еще один контейнер? Огород. Внести в саму структуру? Нарушение абстракции.
W>2. Округлять результат. Не решение — аргумент округления может оказаться "на пике", и сваливаться то в одну, то в другую сторону, пускай и с меньшей вероятностью.
W>3. Включить precise floating point model конкретно в этом месте? А получится ли? Ведь оно может вызывать уже готовый код, который был скомпилирован в быстрой модели.
W>Что посоветуете?
У вас скорее всего все трещит не из-за модели fp, а из-за приблизительности предиката. Модель fp влияет на вычисления, а не на результат сравнения даблов на больше\меньше\равно. Я так понял, что внутри предиката вы делаете вычисления, от них надо избавиться (это ваш вариант 1). Чтобы проблем не было, надо использовать точный предикат, а именно сравнивать уже вычисленные даблы точно (чтобы предикат удовлетворял всем правилам). При этом у вас с сортировкой проблем не должно быть.
Можно поразмыслить над сортировкой сразу двух векторов: в одном данные, а во втором значения, которые используются в предикате. Первое, что нагуглилось:
http://stackoverflow.com/questions/9343846/boost-zip-iterator-and-stdsort