Меня просят преобразовать число с плавающей запятой в 32-битное целое число без знака. Затем я должен проверить, все ли биты равны нулю, но у меня проблемы с этим. Извините, я новичок в C
Это то, что я делаю
float number = 12.5;
// copying number into a 32-bit unsigned int
unsigned int val_number = *((unsigned int*) &number);
На данный момент я очень смущен тем, как проверить, равны ли все биты нулю.
Я думаю, мне нужно перебрать все биты, но я не знаю, как это сделать.
каждое число в вашем компьютере уже «в двоичном виде». Так работает ваш компьютер.
Посмотрите на битовую маскировку и побитовые операции. Это поможет вам начать или определить состояние битов.
и, как говорит Юджин, то, что вы делаете, это наверное, а не то, что вы должны делать, если ваше назначение - перерабатывать. То, что вы делаете, больше похоже на неправильно истолковать float
как unsigned int
, чем на конверсию.
@MarcusMüller Вы имели в виду миссinterpret или реinterpret? :) Не говорю, что это неправильно, хотя
в задании сказано "копировать", неправильный выбор слова от меня
unsigned int val_number = *((unsigned int*) &number);
— это строгое нарушение псевдонимов и, следовательно, неопределенное поведение. И предполагается, что float
имеет тот же размер, что и unsigned int
, что не обязательно должно быть правдой.
«копировать» может быть намеком на использование memcpy
из float
в unsigned
— это устранит нарушение строгого сглаживания.
мой профессор просто хочет, чтобы мы скопировали то, что он сделал в лекции: «Скопируйте биты a и b в 32-битные целые переменные без знака val_a и val_b. Вы не можете просто выполнить присваивание, вам нужно будет привести адреса a и b ввести (unsigned int *), а затем разыменовать адреса"
@Vigilante поздравляет, это будет работать в большинстве случаев, но это является вызов неопределенного поведения. Нет никакой гарантии, что это сработает, даже если что-то скажет вам, если это не сработает.
@Vigilante Его предложение - это указание нарушить определенное правило C (то есть - строгое правило сглаживания). Вы можете указать ему на это. Более безопасным способом было бы использовать memcpy
.
@Vigilante Код вашего профессора нарушает 6.5p7 стандарта C 11. Это строгое нарушение псевдонимов и неопределенное поведение. Если вы хотите скопировать такие байты, вы можете использовать memcpy()
.
Кроме того, кстати, проверка того, является ли IEEE754 полностью нулевым битом, не требует преобразования во что-либо; простой number==0.0f
и проверка знака (signbit(number) != 0
) будет все, что вам нужно.
И если вы обратитесь с этим к своему профессору, как @EugeneSh. предлагает, и если он отвечает что-то вроде «Но это работает», он действительно не понимает C. Лучшее, что он может сказать о таком коде, это: «Я не видел, чтобы он терпел неудачу все же».
@Vigilante Упомянув о проблеме кодирования строгое нарушение псевдонимов, профессор хорошо, даже если они не согласны, будет благосклонно относиться к потенциальной проблеме, как к тому, что должен изучить человек уровня колледжа. Программирование — действительно молодая наука, и передовой опыт постоянно совершенствуется. Если профессионал отмахивается от проблемы, поймите, что многие в реальном мире тоже застряли в колее.
Проверка того, равны ли все биты нулю, эквивалентна проверке того, равно ли число нулю.
Так бы и было int is_zero = (val_number == 0);
IEEE 754 имеет нулевое представление со знаком.
Хорошо, вы говорите о результирующем целом без знака после «преобразования».
Почему есть голосование против этого? Оценка val_number == 0
после того, как val_number
была «преобразована» из float
, выполняет запрошенный тестовый OP: «Затем я должен проверить, все ли биты равны нулю». ОП не просит проверить, имеет ли float
нулевое значение.
Чтобы скопировать байты 32-битного float
в целое число, лучше всего копировать в целочисленный тип, который, безусловно, является 32-битным. unsigned
может быть меньше, столько же или больше 32 бит.
#include <inttypes.h>
float number = 12.5;
uint32_t val_number32; // 32-bit type
memcpy(&val_number32, &number, sizeof val_number32);
Избегайте приведения и назначения. Это приводит к проблемам алиасинга с современными компиляторами @Андрей.
«... нужно привести адреса a и b к типу (unsigned int *), а затем разыменовать адреса» отражает рискованный метод программирования.
Чтобы проверить, все ли биты целого числа без знака равны нулю, просто проверьте константу 0.
int bit_all_zero = (val_number32 == 0);
Альтернативой является использование union
для доступа к байтам из двух разных кодировок.
union {
float val_f;
uint32_t val_u;
} x = { .val_f = 12.5f };
int bit_all_zero = (x.val_u == 0);