Плавающий в двоичный в C

Меня просят преобразовать число с плавающей запятой в 32-битное целое число без знака. Затем я должен проверить, все ли биты равны нулю, но у меня проблемы с этим. Извините, я новичок в C

Это то, что я делаю

float number = 12.5;
// copying number into a 32-bit unsigned int
unsigned int val_number = *((unsigned int*) &number);

На данный момент я очень смущен тем, как проверить, равны ли все биты нулю.

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

Меня просят преобразовать число с плавающей запятой в 32-битное целое число без знака. — для этого требуется точное определение «конвертировать».
Eugene Sh. 08.04.2022 20:07

каждое число в вашем компьютере уже «в двоичном виде». Так работает ваш компьютер.

Marcus Müller 08.04.2022 20:09

Посмотрите на битовую маскировку и побитовые операции. Это поможет вам начать или определить состояние битов.

S3DEV 08.04.2022 20:11

и, как говорит Юджин, то, что вы делаете, это наверное, а не то, что вы должны делать, если ваше назначение - перерабатывать. То, что вы делаете, больше похоже на неправильно истолковать float как unsigned int, чем на конверсию.

Marcus Müller 08.04.2022 20:11

@MarcusMüller Вы имели в виду миссinterpret или реinterpret? :) Не говорю, что это неправильно, хотя

Eugene Sh. 08.04.2022 20:15

в задании сказано "копировать", неправильный выбор слова от меня

Vigilante 08.04.2022 20:18
unsigned int val_number = *((unsigned int*) &number); — это строгое нарушение псевдонимов и, следовательно, неопределенное поведение. И предполагается, что float имеет тот же размер, что и unsigned int, что не обязательно должно быть правдой.
Andrew Henle 08.04.2022 20:19

«копировать» может быть намеком на использование memcpy из float в unsigned — это устранит нарушение строгого сглаживания.

Eugene Sh. 08.04.2022 20:22

мой профессор просто хочет, чтобы мы скопировали то, что он сделал в лекции: «Скопируйте биты a и b в 32-битные целые переменные без знака val_a и val_b. Вы не можете просто выполнить присваивание, вам нужно будет привести адреса a и b ввести (unsigned int *), а затем разыменовать адреса"

Vigilante 08.04.2022 20:24

@Vigilante поздравляет, это будет работать в большинстве случаев, но это является вызов неопределенного поведения. Нет никакой гарантии, что это сработает, даже если что-то скажет вам, если это не сработает.

Marcus Müller 08.04.2022 20:26

@Vigilante Его предложение - это указание нарушить определенное правило C (то есть - строгое правило сглаживания). Вы можете указать ему на это. Более безопасным способом было бы использовать memcpy.

Eugene Sh. 08.04.2022 20:27

@Vigilante Код вашего профессора нарушает 6.5p7 стандарта C 11. Это строгое нарушение псевдонимов и неопределенное поведение. Если вы хотите скопировать такие байты, вы можете использовать memcpy().

Andrew Henle 08.04.2022 20:28

Кроме того, кстати, проверка того, является ли IEEE754 полностью нулевым битом, не требует преобразования во что-либо; простой number==0.0f и проверка знака (signbit(number) != 0) будет все, что вам нужно.

Marcus Müller 08.04.2022 20:29

И если вы обратитесь с этим к своему профессору, как @EugeneSh. предлагает, и если он отвечает что-то вроде «Но это работает», он действительно не понимает C. Лучшее, что он может сказать о таком коде, это: «Я не видел, чтобы он терпел неудачу все же».

Andrew Henle 08.04.2022 20:31

@Vigilante Упомянув о проблеме кодирования строгое нарушение псевдонимов, профессор хорошо, даже если они не согласны, будет благосклонно относиться к потенциальной проблеме, как к тому, что должен изучить человек уровня колледжа. Программирование — действительно молодая наука, и передовой опыт постоянно совершенствуется. Если профессионал отмахивается от проблемы, поймите, что многие в реальном мире тоже застряли в колее.

chux - Reinstate Monica 08.04.2022 21:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
15
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проверка того, равны ли все биты нулю, эквивалентна проверке того, равно ли число нулю.

Так бы и было int is_zero = (val_number == 0);

IEEE 754 имеет нулевое представление со знаком.

Eugene Sh. 08.04.2022 20:14

Хорошо, вы говорите о результирующем целом без знака после «преобразования».

Eugene Sh. 08.04.2022 20:20

Почему есть голосование против этого? Оценка val_number == 0 после того, как val_number была «преобразована» из float, выполняет запрошенный тестовый OP: «Затем я должен проверить, все ли биты равны нулю». ОП не просит проверить, имеет ли float нулевое значение.

Eric Postpischil 08.04.2022 20:36
Ответ принят как подходящий

Чтобы скопировать байты 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);

Другие вопросы по теме