Альтернатива C++11 std::nextafter и std::nexttoward для C++03?

Как следует из названия, функциональность, которая мне нужна, предоставляется математическими библиотеками С++ 11 для поиска следующего значения с плавающей запятой в направлении определенного значения.

Помимо извлечения кода из стандартной библиотеки (к чему мне, возможно, придется прибегнуть), есть ли какие-либо альтернативы для этого с С++ 03 (с использованием GCC 4.4.6)?


person Dan    schedule 02.05.2013    source источник


Ответы (1)


В зависимости от платформы, предполагая IEEE754 и порядок байтов по модулю, вы можете хранить данные числа с плавающей запятой в виде целого числа, увеличивать на единицу и получать результат:

float input = 3.15;

uint32_t tmp;

unsigned char * p = reinterpret_cast<unsigned char *>(&tmp);
unsigned char * q = reinterpret_cast<unsigned char *>(&input);

p[0] = q[0]; p[1] = q[1]; p[2] = q[2]; p[3] = q[3];  // endianness?!

++tmp;

q[0] = p[0]; q[1] = p[1]; q[2] = p[2]; q[3] = p[3];

return input;

Остерегайтесь нулей, NaN и бесконечностей, конечно.

person Kerrek SB    schedule 02.05.2013
comment
Обратите внимание, что для уменьшения отрицательного числа с плавающей запятой необходимо увеличить его целочисленное представление без знака. - person Pascal Cuoq; 02.05.2013
comment
Что не так с простым std::copy(p, p+4, q) ? Или, предполагая, что выравнивание равно, просто reinterpret_cast<uint32_t&>(input)++; - person MSalters; 02.05.2013
comment
Ты слишком усложняешь. memcpy делает то, что вы хотите. И на большинстве машин reinterpret_cast<unsigned const*>( &input ) или помещая их в union. (И порядок следования байтов будет проблемой только в том случае, если числа с плавающей запятой и целые числа имеют разный порядок следования байтов — о чем я никогда не слышал.) - person James Kanze; 02.05.2013
comment
@MSalters: std::copy в порядке. Сегодня мне не хотелось пользоваться библиотекой. Ваш прямой актерский состав — UB. - person Kerrek SB; 02.05.2013
comment
@KerrekSB: Возможно, но в любом случае это зависело от платформы, и я видел, что таким образом генерировался лучший код (компилятор сохранял переменную в том же регистре). - person MSalters; 02.05.2013
comment
@MSalters: Хм... типичные процессоры имеют отдельный набор регистров для чисел с плавающей запятой... - person Kerrek SB; 02.05.2013
comment
@KerrekSB: Оглядываясь назад, можно сказать, что это более умная конструкция процессора. Это позволяет вам иметь больше регистров для одной и той же длины инструкции, поскольку код операции помогает устранить неоднозначность между регистром int 0 и регистром FP ​​0. Но, как показывает x86, дизайн ISA — это больше искусство, чем наука. - person MSalters; 03.05.2013
comment
@MSalters: Ну, как только вы берете адрес чего-то, я полагаю, это все равно нужно записать в память ... - person Kerrek SB; 03.05.2013
comment
@KerrekSB: reinterpret_cast<uint32_t&> хороша тем, что адрес не используется. И на моей цели, у которой нет отдельных регистров FP, это даже не включало копирование регистра в регистр. - person MSalters; 03.05.2013