Как выполнить битовую операцию на числах с плавающей точкой

Вы можете использовать pkgutil.walk_packages:

from pkgutil import walk_packages
possible_packages = [module for _, module, _ in walk_packages()]
45
задан Community 23 May 2017 в 12:02
поделиться

6 ответов

На уровне языка не существует такой вещи, как «побитовые операции с числами с плавающей запятой». Побитовые операции в C / C ++ работают с представлением числа в виде значений. А представление значений чисел с плавающей запятой не определено в C / C ++. Числа с плавающей запятой не имеют битов на уровне представления значений, поэтому вы не можете применять к ним побитовые операции.

Все, что вы можете сделать, это проанализировать битовое содержимое необработанной памяти, занятой числами с плавающей запятой. номер точки. Для этого вам нужно либо использовать объединение, как предложено ниже, либо (эквивалентно и только в C ++) переинтерпретировать объект с плавающей запятой как массив объектов unsigned char , как в

float f = 5;
unsigned char *c = reinterpret_cast<unsigned char *>(&f);
// inspect memory from c[0] to c[sizeof f - 1]

И, пожалуйста, не Не пытайтесь переинтерпретировать объект float как объект int , как предлагают другие ответы. В этом нет особого смысла, это незаконно и не гарантируется, что это будет работать в компиляторах, которые следуют правилам строгого псевдонима при оптимизации. Единственный законный способ проверить содержимое памяти в C ++ - интерпретировать его как массив [подписанный / беззнаковый] char .

Также обратите внимание, что технически вам не гарантируется, что представление с плавающей запятой на вашем система соответствует стандарту IEEE754 (хотя на практике это так, если вы явно не разрешите этому не быть, и то только в отношении -0,0, ± бесконечность и NaN).

73
ответ дан 26 November 2019 в 21:03
поделиться

Можно работать приблизительно строго искажающее правило и выполнить битовые операции на float каламбуривший типом как uint32_t (если реализация определяет его, который большинство делает) без неопределенного поведения при помощи memcpy() :

float a = 1.4123f;
uint32_t b;

std::memcpy(&b, &a, 4);
// perform bitwise operation
b &= 1u << 3;
std::memcpy(&a, &b, 4);
2
ответ дан 26 November 2019 в 21:03
поделиться

Обратите внимание на следующее. На основе быстрого обратного квадратного корня:

#include <iostream>
using namespace std;

int main()
{
    float x, td = 2.0;
    int ti = *(int*) &td;
    cout << "Cast int: " << ti << endl;
    ti = ti>>4;
    x = *(float*) &ti;
    cout << "Recast float: " << x << endl;
    return 0; 
}
4
ответ дан 26 November 2019 в 21:03
поделиться

@mobrule:

Лучше:

#include <stdint.h>
...
union fp_bit_twiddler {
    float f;
    uint32_t u;
} q;

/* mutatis mutandis ... */

Для эти значения int, вероятно, подойдут, но как правило, вы должны использовать целые числа без знака для сдвига битов, чтобы избежать эффектов арифметических сдвигов. А также uint32_t будет работать даже в системах, чьи int не являются 32-битными.

2
ответ дан 26 November 2019 в 21:03
поделиться

Если вы пытаетесь изменить биты в представлении с плавающей запятой, вы можете сделать что-то вроде этого:

union fp_bit_twiddler {
    float f;
    int i;
} q;
q.f = a;
q.i &= (1 << 3);
a = q.f;

Как отмечает AndreyT, доступ к подобному объединению вызывает неопределенное поведение, а компилятор мог отрастить руки и задушить вас. Вместо этого сделайте то, что он предлагает.

17
ответ дан 26 November 2019 в 21:03
поделиться
float a = 1.4123;
unsigned int* inta = reinterpret_cast<unsigned int*>(&a);
*inta = *inta & (1 << 3);
6
ответ дан 26 November 2019 в 21:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: