2014-09-02 2 views
-3

Я хочу сделать дополнение двух поплавок.Два дополнения и потеря информации в C

unsigned long Temperature ; 
    Temperature = (~(unsigned long)(564.48))+1; 

Но проблема в том, что литье данных теряет информацию, 564 вместо 564.48. Могу ли я сделать дополнение двух без потери информации?

+4

'564.48'' '' double', литье в 'unsigned long' усекает его до' 564'. Что вы ожидаете? –

+0

Значение memcpy float для unsigned long, а затем примените компонент two. Или используйте union с float и unsigned long, назначьте 564.48f для float и примените компонент two к unsigned long. –

+0

@AlexFarber: Все они будут отображаться UB. – bitmask

ответ

0

Приведение значения с плавающей запятой в целочисленное значение изменяет «содержимое бита» этого значения.

Для выполнения двоичного дополнения на «битное содержание» ценность с плавающей точкой:

float f = 564.48f; 
unsigned long Temperature = ~*(unsigned long*)&f+1; 

Убедитесь, что sizeof(long) == sizeof(float) или использовать double вместо float.

+2

Выполнение двух дополнений к битовому содержимому поплавка - совершенно бессмысленная операция. – interjay

+0

@interjay: Это стоит упомянуть. Я подумал об этом, но подумал, что у ОР могут быть свои причины (возможно, нужно записать его в регистр или сохранить в какой-нибудь двоичной базе данных и т. Д.). –

+0

в C++ это UB из-за строгого правила псевдонимов. Я не уверен в C, я думаю, что все в порядке на C, можете ли вы подтвердить? – bolov

1

Это очень странная вещь; числа с плавающей запятой - , а не, хранящиеся в качестве дополнения 2s, поэтому это не имеет большого смысла.

Во всяком случае, возможно, вы можете использовать старый добрый union трюк:

union { 
    float real; 
    unsigned long integer; 
} tmp = { 564.48 }; 

tmp.integer = ~tmp.integer + 1; 
printf("I got %f\n", tmp.real); 

Когда я попробовал (на ideone) он напечатал:

I got -0.007412 

Обратите внимание, что это зависит от неустановленного поведения , поэтому возможно, что он может сломаться, если ваш компилятор не реализует доступ самым прямым способом. Это отличная форма undefined поведение (что сделало бы код недействительным), но все же не оптимальным. Кто-то сказал мне, что более новые стандарты делают это яснее, но я не нашел точной ссылки, поэтому ... подумайте о себе, предупредив вас.

+0

Не знаете, откуда у вас «безопасно в современных компиляторах»? – tangrs

+0

@tangrs Я тоже ... Я переписал его, чтобы сделать его более ясным. – unwind

+0

Возможно, я ошибаюсь, но кажется, что OP хочет '(~ tmp.integer) + 1' вместо' ~ tmp.integer + 1' –

1

Вы не можете использовать ~ над поплавками (он должен быть целочисленный тип):

#include <stdio.h> 

void print_binary(size_t const size, void const * const ptr) 
{ 
    unsigned char *b = (unsigned char *) ptr; 
    unsigned char byte; 
    int i, j; 

    for (i = size - 1; i >= 0; i--) { 
     for (j = 7; j >= 0; j--) { 
      byte = b[i] & (1 << j); 
      byte >>= j; 
      printf("%u", byte); 
     } 
    } 
    printf("\n"); 
} 

int main(void) 
{ 
    float f = 564.48f; 
    char *p = (char *)&f; 
    size_t i; 

    print_binary(sizeof(f), &f); 
    for (i = 0; i < sizeof(float); i++) { 
     p[i] = ~p[i]; 
    } 
    print_binary(sizeof(f), &f); 
    f += 1.f; 
    return 0; 
} 

Выход:

01000100000011010001111010111000 
10111011111100101110000101000111 

Конечно print_binary есть для теста результат, удалите его, и (как указывал @barakmanos) print_binary предполагает малоконечную величину, остальная часть кода не зависит от endiannes:

#include <stdio.h> 

int main(void) 
{ 
    float f = 564.48f; 
    char *p = (char *)&f; 
    size_t i; 

    for (i = 0; i < sizeof(float); i++) { 
     p[i] = ~p[i]; 
    } 
    f += 1.f; 
    return 0; 
} 
+0

Приведёт разные результаты в отношении больших и малых чисел. –

+0

@barakmanos, вы уверены? Endianess влияет только на порядок байтов. Поскольку 'char' - это точно один байт, он одинаковый во всех форматах endianess. [Посмотрите] (http://stackoverflow.com/q/21761952/1606345) –

+1

Да, но вы вызываете 'float *' в 'char *' при вызове 'print_binary'. –

Смежные вопросы