Как правильно записать плавающее значение в файл bin - PullRequest
2 голосов
/ 26 апреля 2010

Я пытаюсь вывести значения с плавающей запятой из моей программы в файл bin. Поскольку я не могу использовать какую-либо функцию stdlib, я подумываю записать ее char в char в большой массив char, который я выгружаю в своем тестовом приложении в файл.

Это как

float a=3132.000001;

Я буду выгружать это в массив символов в 4 байта.

Пример кода: -

if((a < 1.0) && (a > 1.0) || (a > -1.0 && a < 0.0))
    a = a*1000000 // 6 bit fraction part.

Не могли бы вы помочь мне написать это лучше.

Ответы [ 3 ]

4 голосов
/ 26 апреля 2010

Предполагая, что вы планируете читать его обратно в ту же программу на той же архитектуре (без проблем с порядком байтов), просто напишите число напрямую:

fwrite(&a, sizeof(a), 1, f);

или скопируйте его с помощью memcpy в промежуточный буфер:

memcpy(bufp, &a, sizeof(a));
bufp += sizeof(a);

Если вам приходится иметь дело с проблемами порядка байтов, вы можете быть хитрым. Примените float к long и используйте htonl:

assert(sizeof(float) == sizeof(long)); // Just to be sure
long n = htonl(*(long*)&a);
memcpy(bufp, &n, sizeof(n));
bufp += sizeof(n);

Чтение обратно в:

assert(sizeof(float) == sizeof(long)); // Just to be sure
long n;
memcpy(&n, bufp, sizeof(n));
n = ntohl(n);
a = *(float*)n;
bufp += sizeof(n);
1 голос
/ 26 апреля 2010

Использование frexp.

int32_t exponent, mantissa;
mantissa = frexp( a, &exponent ) / FLT_EPSILON;

Знак захвачен в мантиссе. Это должно правильно обрабатывать денормали, но не бесконечность или NaN.

Запись exponent и mantissa обязательно займет более 4 байтов, поскольку неявный бит мантиссы был сделан явным. Если вы хотите записать число с плавающей точкой как необработанные данные, вопрос вовсе не в значениях с плавающей точкой, а в обработке необработанных данных и порядковых номеров.

На другом конце используйте ldexp.

Если бы вы могли использовать стандартную библиотеку, printf имеет спецификатор формата только для этого: %a. Но, возможно, вы считаете frexp стандартной библиотекой. Не ясно.

0 голосов
/ 26 апреля 2010

Если вы не беспокоитесь о различиях в платформе между читателем и писателем:

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

...

union float_bytes {
    float val;
    uint8_t a[sizeof(float)]; // This type can be unsigned char if you don't have stdint.h
};

size_t float_write(FILE * outf, float f) {
   union float_bytes fb = { .val = f };
   return fwrite(fb.a, sizeof(float), outf);
}

Существуют более короткие способы преобразования числа с плавающей точкой в ​​байтовый массив, но они включают в себя больше типов и их сложнее читать. Другие способы сделать это, вероятно, не делают быстрее или меньше скомпилированный код (хотя объединение сделает код отладки больше).

Если вы пытаетесь хранить поплавки независимым от платформы способом, то самый простой способ сделать это - сохранить его в виде строки (с большим количеством цифр после.). Более сложным является выбор битовой разметки с плавающей запятой для использования и преобразования всех ваших чисел с плавающей запятой в / из этого формата по мере их чтения / записи. Вероятно, просто выберите IEEE с плавающей точкой с определенной шириной и определенным порядком байтов и придерживайтесь этого.

...