Для обработки значений как float
, масштабированных на 1e12
, и вычисления следующей большей степени двух, например, "rounding up (3120000732421875)"
, ключом является понимание того, что вы ищете следующую большую степень двух из 32-битного представления x / 1.0e12
. Хотя вы можете математически получить это значение, значение union
между float
и unsigned
(или uint32_t
) обеспечивает прямой способ интерпретации сохраненного 32-разрядного значения для числа с плавающей запятой в качестве значения без знака. 1
Простым примером использования объединения prev
для хранения уменьшенного значения x
и отдельного экземпляра next
, содержащего значение без знака (+1
), может быть:
#include <stdio.h>
#include <inttypes.h>
int main (void) {
uint64_t x = 3120000500000000;
union { /* union between float and uint32_t */
float f;
uint32_t u;
} prev = { .f = x / 1.0e12 }, /* x reduced to float, pwr of 2 as .u */
next = { .u = prev.u + 1u }; /* 2nd union, increment pwr of 2 by 1 */
printf ("prev : %" PRIu64 "\n x : %" PRIu64 "\nnext : %" PRIu64 "\n",
(uint64_t)(prev.f * 1e12), x, (uint64_t)(next.f * 1e12));
}
Пример использования / Вывод
$ ./bin/pwr2_prev_next
prev : 3120000488281250
x : 3120000500000000
next : 3120000732421875
Примечания:
1. В качестве альтернативы вы можете использовать указатель на char
для хранения адреса типа с плавающей запятой и интерпретации 4-байтового значения, хранящегося в этом месте как unsigned
без нарушения C11 Standard - §6.5 Выражения (p6,7) ( «Строгое правило алиасинга» ), но использование union
является предпочтительным .