2013-03-15 3 views
6

В C++ предположим, что у меня есть номер x типа T, который может быть целым или с плавающей точкой. Я хочу найти самый большой номер y типа T, для которого y < x. Решение должно быть шаблоном для прозрачной работы с целыми числами и числами с плавающей запятой. Вы можете игнорировать край, где x - это самое маленькое число, которое может быть представлено в T.Максимальное количество <x?

ВОЗМОЖНОЕ ИСПОЛЬЗОВАНИЕ СЛУЧАЙ: Этот вопрос был помечен как слишком локализованный, поэтому я хотел бы представить пример использования, который, я думаю, более общий. Обратите внимание, что я не являюсь оригинальным автором OP.

Рассмотрим эту структуру:

struct lower_bound { 
    lower_bound(double value, bool open) : value(open? value+0.1 : value) {} 
    double value; 
    bool operator()(double x) { return x >= value; } 
}; 

Этот класс моделирует нижнюю границу, которые могут либо быть открытыми или закрытыми. Конечно, в реальной (каламбурованной) жизни мы не можем этого делать. Поток невозможен (или, по крайней мере, довольно сложный) для расчета для S, являющегося всеми действительными числами.

enter image description here

Однако, когда S является набором чисел с плавающей точкой, это очень действует принцип, так как мы имеем дело с практически счетным множеством; и тогда нет такой вещи, как открытая или закрытая граница. То есть,> = может быть определено в терминах> как сделано в классе lower_bound.

Для простоты кода я использовал +0.1 для имитации открытой нижней границы. Конечно, 0,1 является сырым значением, так как могут быть значения z такие, что значение < z < = значение + 0,1 или значение + 0,1 == значение в представлении с плавающей запятой. Поэтому @ Brett-бодрый ответ очень полезно :)

Вы можете думать о другом более простое решение:

struct lower_bound { 
    lower_bound(double value, bool open) : open(open), value(value) {} 
    bool open; 
    double value; 
    bool operator()(double x) { return (open ? x > value : x>=value); } 

}; 

Однако это менее эффективно, как SizeOf (LOWER_BOUND) больше, и оператор() потребности для выполнения более сложного оператора. Первая реализация действительно эффективна и может быть реализована просто как двойная, а не структура. Технически единственная причина использовать вторую реализацию состоит в том, что вы предполагаете, что double является непрерывным, в то время как это не так, и я думаю, что в обозримом будущем этого не будет.

Надеюсь, что я создал и объяснил действительный прецедент, и что я не обидел автора.

+1

Можете ли вы привести пример того, что это было бы для типов с плавающей точкой? Означает ли это, что мантисса 'y' меньше на один бит, а показатель тот же? – angelatlarge

+3

Я ожидаю большего от пользователя 27.5k. – 2013-03-15 19:18:48

+0

Вы .. вы что-нибудь пробовали? – Rapptz

ответ

11

Если у вас есть C++ 11, вы можете использовать std::nextafter в <cmath>:

if (std::is_integral<T>::value) 
    return (x - 1); 
else 
    return std::nextafter(x, - std::numeric_limits<T>::infinity()); 
+0

[x-1.0 может быть равным x для плавающих типов, и это происходит для многих чисел> = ~ 33554432] (http : //coliru.stacked-crooked.com/view? id = cc0ae3f34df4c559275ba1290458f077-61c3814520a8d4318f681038dc4b4da7) –

+0

@MooingDuck - да, спасибо. Это было поспешное. Я понимаю относительное и абсолютное ute ошибка. –

+0

@BrettHale: Легкий надзор, чтобы сделать, я уверен, что это все над моим кодом тоже. –

Смежные вопросы