Плавающие битовые операции - PullRequest
1 голос
/ 17 марта 2011

Я хочу преобразовать хранилище числа с плавающей запятой в целое число (значение 'число' не обязательно должно быть равным).

Если число с плавающей запятой (например, 10) представлено в двоичном виде(по крайней мере, в моей реализации) как:

01000001001000000000000000000000

Тогда он должен (также в моей реализации) представлять целочисленное значение 1092616192.

В настоящее время я делаю это с помощью следующего:

union UNFI {
    float a;
    int b;
};

UNFI n;
n.a = 10;
int bits = n.b; // foo!

for (int i=31; i>=0; --i) {
    bool bit = ((bits >> i) & 1);
    std::cout << bit;
}

Что является достижением того, что я хотел бы, но это, по своей природе, неопределенное поведение.Поэтому я хотел бы знать, каков «правильный» способ достижения этого результата.

Из стандарта C99:

With one exception, if the value of a member of a union object is used when the most recent store to the object was to a different member,the behavior is implementation-defined.

Разве это не неопределенное поведение?

Ответы [ 3 ]

3 голосов
/ 17 марта 2011

Правильный способ - позвонить memcpy.Большинство компиляторов оптимизируют это для эффективного доступа к памяти из одного слова, как и объединение, но на платформах с дополнительными требованиями к выравниванию они будут делать правильные вещи.И это никогда не вызовет сигнализацию NaN.

float a = 10;

char bits[sizeof a];
memcpy(bits, &a, sizeof a);

или

int b;
static_assert(sizeof b == sizeof a);
memcpy(&b, &a, sizeof a);
0 голосов
/ 17 марта 2011

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

int const bits = *(reinterpret_cast<int *>(&n))
0 голосов
/ 17 марта 2011

Что не определено?
Расположение IEEE с плавающей точкой очень хорошо определено, единственным дополнительным усложнением является упорядочение байтов на вашей платформе (и насколько велико int)

...