упаковка float/double
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.03.20 16:41
Оценка:
привет!

задумался над сабжем.
поситал по теме(https://habr.com/ru/post/112953/), но, признаюсь, многого не понял.
гугления тоже какие-то бестолковые...

может кто расскажет что по теме?

подумал, что можно использовать modf() чтоб разбить на части. знак тоже понятно как получить.
с интегральной частью вроде все понятно...
но как быть с экпонентой? как ее привести к целому? как хранить кол-во нулей?

какие мысли?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: упаковка float/double
От: Zhendos  
Дата: 06.03.20 17:10
Оценка: 1 (1)
Здравствуйте, niXman, Вы писали:

X>привет!


X>задумался над сабжем.

X>поситал по теме(https://habr.com/ru/post/112953/), но, признаюсь, многого не понял.
X>гугления тоже какие-то бестолковые...

X>может кто расскажет что по теме?


Непонятно зачем это нужно, но можно просто открыть /usr/include/ieee754.h и там будет:

union ieee754_float
  {
    float f;

    /* This is the IEEE 754 single-precision format.  */
    struct
      {
        unsigned int mantissa:23;
        unsigned int exponent:8;
        unsigned int negative:1;
      } ieee;

    /* This format makes it easier to see if a NaN is a signalling NaN.  */
    struct
      {
        unsigned int mantissa:22;
        unsigned int quiet_nan:1;
        unsigned int exponent:8;
        unsigned int negative:1;
      } ieee_nan;
  };


X>подумал, что можно использовать modf() чтоб разбить на части. знак тоже понятно как получить.

X>с интегральной частью вроде все понятно...
X>но как быть с экпонентой? как ее привести к целому? как хранить кол-во нулей?

X>какие мысли?


Еще есть https://en.cppreference.com/w/cpp/numeric/math/frexp ,
но нафига если можно просто битики извлечь
Re: упаковка float/double
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.03.20 18:50
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>может кто расскажет что по теме?


А что непонятно-то?

Чтобы точно представлять вещественные числа во всем интересном диапазоне, надо очень много бит. Но обычно такая точность не нужна. Скажем, если мы работаем с десятками миллиардов, то ошибка плюс-минус единицы для многих (но не всех!) задач не существенна.

Поэтому используется представление в виде 2^e * m, где m — мантисса, e — экспонента. Это позволяет, за счет ограничения точности, уложиться в фиксированный размер. И экспонента и мантисса при этом знаковые.

Конкретных раскладок по битам исторически было много, но сейчас более-менее победил IEEE 754. Все актуальные процессоры поддерживают его прямо в аппаратуре.
Re[2]: упаковка float/double
От: niXman Ниоткуда https://github.com/niXman
Дата: 07.03.20 10:55
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Непонятно зачем это нужно, но можно просто открыть /usr/include/ieee754.h и там будет:

...
Z>Еще есть https://en.cppreference.com/w/cpp/numeric/math/frexp ,

перед тем как запостить я ознакомился с приведенными тобою обеими вариантами, и у каждого свои минусы.
и чтоб не задавать вопросы по минусовым моментам, я решил задать ТОП вопрос, вдруг ничего изобретать не придется =)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: упаковка float/double
От: kov_serg Россия  
Дата: 07.03.20 12:02
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>задумался над сабжем.

X>поситал по теме(https://habr.com/ru/post/112953/), но, признаюсь, многого не понял.
X>гугления тоже какие-то бестолковые...

X>может кто расскажет что по теме?

https://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B2%D0%B5%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D1%87%D0%B8%D1%81%D0%B5%D0%BB
https://processors.wiki.ti.com/index.php/Floating_Point_Optimization

X>но как быть с экпонентой? как ее привести к целому? как хранить кол-во нулей?

X>какие мысли?
А что не понятного.
1. вариант прямо из бинарных данных вынимать (из минусов расположение байтов не регламентируется, и под конкретную платформу может значительно отличаться)
2. просто вычислить с помощью мат функции, лгарифма, умножения, сложения и сравнения. Правда для не чисел придётся всё равно вынимать из бинарного представления (при условии что оно как-то используется).
  например
#include <math.h>
#include <stdio.h>

int show(double x,int (*print)(void* ctx,const char* s),void* ctx) {
    enum { k_max=52 }; char buf[2];
    int k,e,z; double frac;
    if (x==0) {
        if (1/x<0) print(ctx,"-");
        return print(ctx,"0");
    }
    if (x<0) print(ctx,"-");
    if (x!=x) return print(ctx,"NAN");
    if (2*x==x) return print(ctx,"INF");
    if (x<0) x=-x;
    e=floor(log2(x));
    frac=x*pow(2,-e);
    //{ long long f=floor((frac-1)*pow(2.0,k_max)); printf(" f=%013llX ",f); }
    print(ctx,"1.");
    for(k=0;k<k_max;++k) {
        if (frac>=1) frac-=1;
        frac*=2;
        if (frac>=1) print(ctx,"1"); else print(ctx,"0");
    }
    print(ctx,"p");
    if (e<0) { print(ctx,"-"); e=-e; }
    z=10; while (z<=e) z*=10;
    for(buf[1]=0;z>=10;) { 
        z/=10; buf[0]='0'+(e/z%10);
        print(ctx,buf);
    }
    return 0;
}

int print(void*,const char* s) { printf("%s",s); return 0; }
void check(double x,const char* s) {
    printf("%s = ",s);
    show(x,print,0); 
    printf("\n");
}

int main(int argc, char const *argv[]) {
    check(1          , "1    ");
    check(2          , "2    ");
    check(100        , "100  ");
    check(0.5        , "0.5  ");
    check(0.125      , "0.125");
    check(1.5        , "1.5  ");
    check(1.0/3      , "1/3  ");
    check(-1.0/3     , "-1/3 ");
    check(1e-30      , "1e-30");
    check(1e+30      , "1e+30");
    check( 0.0       , "0    ");
    check(-0.0       , "-0   ");
    check(1/sqrt(0)  , "+INF ");
    check(-1/sqrt(0) , "-INF ");
    check(sqrt(-1)   , "NAN  ");
    return 0;
}

1     = 1.0000000000000000000000000000000000000000000000000000p0
2     = 1.0000000000000000000000000000000000000000000000000000p1
100   = 1.1001000000000000000000000000000000000000000000000000p6
0.5   = 1.0000000000000000000000000000000000000000000000000000p-1
0.125 = 1.0000000000000000000000000000000000000000000000000000p-3
1.5   = 1.1000000000000000000000000000000000000000000000000000p0
1/3   = 1.0101010101010101010101010101010101010101010101010101p-2
-1/3  = -1.0101010101010101010101010101010101010101010101010101p-2
1e-30 = 1.0100010010000100101111111110111010111100001010100000p-100
1e+30 = 1.1001001111100101100100111001101000001000110011101010p99
0     = 0
-0    = -0
+INF  = INF
-INF  = -INF
NAN   = NAN
Re: упаковка float/double
От: B0FEE664  
Дата: 09.03.20 13:03
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>задумался над сабжем.


Я тоже над ним задумался. Что значит "упаковка float/double"?
И каждый день — без права на ошибку...
Re[2]: упаковка float/double
От: Chorkov Россия  
Дата: 11.03.20 08:30
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Я тоже над ним задумался. Что значит "упаковка float/double"?


Бинарное представление float и double, в контексте задачи сериализации.
Т.е. перекладывание битиков чисел, из платформенно-зависимого представления в принятое на x86 и обратно.

Стандарт IEEE754 оставляет производителям процессоров некоторую свободу в выборе бинарного представления.

Хотя, по факту, все только преставляют байты (little/big endian).
Во всяком случае, авторы HDF5 (кому как не им знать про переносимость double?) оперируют только этими двумя представлениями double (H5T_IEEE_F64LE, H5T_IEEE_F64BE). Остальные ***_F64 типы — ссылки на эти представления.
Re: упаковка float/double
От: andyp  
Дата: 11.03.20 08:48
Оценка:
Здравствуйте, niXman, Вы писали:

X>какие мысли?


Сохранять непосредственно байты в little endian (можно в big, с чем чаще предполагается сталкиваться, чтобы минимизировать перепаковки на самых ходовых архитектурах). Распаковывать с учетом endian архитектуры. На экзотику забить?
Re[3]: упаковка float/double
От: B0FEE664  
Дата: 11.03.20 09:29
Оценка:
Здравствуйте, Chorkov, Вы писали:

BFE>>Я тоже над ним задумался. Что значит "упаковка float/double"?

C>Бинарное представление float и double, в контексте задачи сериализации.
C>Т.е. перекладывание битиков чисел, из платформенно-зависимого представления в принятое на x86 и обратно.

Разве вот это
Автор: watchmaker
Дата: 10.04.19
не является ответом?

PS Стандарта на бинарное представление нет для целых чисел так же, как и для других чисел, так что нет смысла особо с этим заморачиваться. К тому же сериализованные данные не предназначены, для переноса с одной системы на другую. Если же вы всё же пытаетесь перенести данные с одной системы на другую, то от бинарного представления лучше отказаться, ведь, например, нет гарантии, что, скажем, int — это 4 байта. Всякие там JSON и XML не просто так придуманы.
И каждый день — без права на ошибку...
Отредактировано 11.03.2020 9:44 B0FEE664 . Предыдущая версия .
Re[4]: упаковка float/double
От: Chorkov Россия  
Дата: 11.03.20 10:07
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, Chorkov, Вы писали:


BFE>>>Я тоже над ним задумался. Что значит "упаковка float/double"?

C>>Бинарное представление float и double, в контексте задачи сериализации.
C>>Т.е. перекладывание битиков чисел, из платформенно-зависимого представления в принятое на x86 и обратно.

BFE>Разве вот это
Автор: watchmaker
Дата: 10.04.19
не является ответом?


BFE>PS Стандарта на бинарное представление нет для целых чисел так же, как и для других чисел, так что нет смысла особо с этим заморачиваться. К тому же сериализованные данные не предназначены, для переноса с одной системы на другую. Если же вы всё же пытаетесь перенести данные с одной системы на другую, то от бинарного представления лучше отказаться, ведь, например, нет гарантии, что, скажем, int — это 4 байта. Всякие там JSON и XML не просто так придуманы.


У тесктовой сериализации своя ниша, у бинарной — своя.

Текстовые форматы часто неприменимы не потому:
1) занимают в 2 раза больше места (а значат пишутся/читаются в 2 раза медленнее),
2) потому что требуют полной загрузки в память для обработки (столько памяти на одном узле может просто не быть). Попробуйте достать 100500-й элемент матрицы, если она в текстовом представлении.
3) текст порождает проблемы при попытке работать с одним файлом из нескольких процессов / с нескольких узлов на расперделенной FS...
Приходится разбивать данные по отдельным файлам, что неудобно.
Re: упаковка float/double
От: reversecode google
Дата: 11.03.20 10:18
Оценка:
посмотреть как сериализуют другие фреймворки религия не позволяет ?
Re[5]: упаковка float/double
От: B0FEE664  
Дата: 11.03.20 11:30
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>У тесктовой сериализации своя ниша, у бинарной — своя.


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

C>Текстовые форматы часто неприменимы не потому:

C>1) занимают в 2 раза больше места (а значат пишутся/читаются в 2 раза медленнее),

Казалось бы это важно, а на самом деле нет. Посмотрим на передачу web-страниц в интернете. Даже тогда, когда использовали телефонные линии и модемы, никто не передавал web-страницы в бинарном виде. А ведь казалось бы: сколько можно сэкономить, если разметку кодировать в бинарном виде! Однако нет: передача осуществлялась и осуществляется в тексте, а бинарная упаковка (зжатие) производится на уровне передачи.

C>2) потому что требуют полной загрузки в память для обработки (столько памяти на одном узле может просто не быть). Попробуйте достать 100500-й элемент матрицы, если она в текстовом представлении.

Зачем полная загрузка в память? Если вам нужен конкретный элемент, то всё остальное можно отбросить ещё на этапе чтения.

C>3) текст порождает проблемы при попытке работать с одним файлом из нескольких процессов / с нескольких узлов на расперделенной FS...

C> Приходится разбивать данные по отдельным файлам, что неудобно.

Это как? Всё же ровно наоборот: я никогда не видел, чтобы мержили бинарные файлы, а вот текстовые — каждый день.


Но вообще всё это ерунда по сравнению с проблемами, которые возникают как только оказывается, что нужно поменять или добавить новое данное в файл. С текстом всё просто: старые версии программы просто не видят новые элементы поэтому, при желании, можно даже организовать прямую совместимость. Новые версии программы видят и понимают старые и новые форматы. А вот с бинарными форматами оказывается всё намного сложнее: чтобы прочитать старую версию файла данных в новой версии программы придётся сохранять специальный парсер, который выберет данные в старые структуры, а потом придётся ещё писать код, который старые структуры сконвертирует в новое представление. К тому же большенство сериализаторов не проверяют корректность входных данных, так что подобрать данные, которые заваливают приложение обычно не состовляет труда, что, понятно, пораждает секьюрные проблемы.
И каждый день — без права на ошибку...
Re[6]: упаковка float/double
От: Chorkov Россия  
Дата: 11.03.20 13:21
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, Chorkov, Вы писали:


C>>У тесктовой сериализации своя ниша, у бинарной — своя.


BFE>Я не знаю, о каких нишах вы говорите, а вот из опыта мне известно, что экономия на текстовом представлении приводит к большим проблемам при использовании продукта.


C>>Текстовые форматы часто неприменимы не потому:

C>>1) занимают в 2 раза больше места (а значат пишутся/читаются в 2 раза медленнее),

BFE>Казалось бы это важно, а на самом деле нет. Посмотрим на передачу web-страниц в интернете. Даже тогда, когда использовали телефонные линии и модемы, никто не передавал web-страницы в бинарном виде. А ведь казалось бы: сколько можно сэкономить, если разметку кодировать в бинарном виде! Однако нет: передача осуществлялась и осуществляется в тексте, а бинарная упаковка (зжатие) производится на уровне передачи.


Никого не удивляет, что все форматы хранения видео — бинарные?

C>>2) потому что требуют полной загрузки в память для обработки (столько памяти на одном узле может просто не быть). Попробуйте достать 100500-й элемент матрицы, если она в текстовом представлении.

BFE>Зачем полная загрузка в память? Если вам нужен конкретный элемент, то всё остальное можно отбросить ещё на этапе чтения.

Когда понадобится 100499-й снова от начала файла отсчитывать?
В случае бинарного представления можно прочитать с диска только один нужный кластер/страницу памяти.

C>>3) текст порождает проблемы при попытке работать с одним файлом из нескольких процессов / с нескольких узлов на расперделенной FS...

C>> Приходится разбивать данные по отдельным файлам, что неудобно.

BFE>Это как? Всё же ровно наоборот: я никогда не видел, чтобы мержили бинарные файлы, а вот текстовые — каждый день.


Не мерджить, а одновременно писать в один файл.
Например: считаем аэродинамичеку на MPI-кластере на 16 машинах (по 8 процессов на машину).
Процессы поделили пространственную сетку и обмененеваются только данными по состоянию на граничных узлах.
Надо записать на диск поля скоростей и даления и температуры на заданный момент времени. (~ 1 Tb данных)
Если задействовать контролеры дисков всех 16 машин, то данные можно записать в 16 раз быстрее чем при последовательной записи (что неизбежно в случае текстового формата).


BFE>Но вообще всё это ерунда по сравнению с проблемами, которые возникают как только оказывается, что нужно поменять или добавить новое данное в файл. С текстом всё просто: старые версии программы просто не видят новые элементы поэтому, при желании, можно даже организовать прямую совместимость. Новые версии программы видят и понимают старые и новые форматы. А вот с бинарными форматами оказывается всё намного сложнее: чтобы прочитать старую версию файла данных в новой версии программы придётся сохранять специальный парсер, который выберет данные в старые структуры, а потом придётся ещё писать код, который старые структуры сконвертирует в новое представление. К тому же большенство сериализаторов не проверяют корректность входных данных, так что подобрать данные, которые заваливают приложение обычно не состовляет труда, что, понятно, пораждает секьюрные проблемы.


Бинарный формат вовсе не исключает текстовых названий полей и атрибутов.
HDF придумали еще в начале 90-х (до этого были и другие форматы). Все эти проблемы давно решены.

P.S.
Пора переносить тему в священные войны.
Re[7]: упаковка float/double
От: B0FEE664  
Дата: 11.03.20 14:03
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>Никого не удивляет, что все форматы хранения видео — бинарные?

Нет, не удивляет, ведь по сути это одно данное.

C>Когда понадобится 100499-й снова от начала файла отсчитывать?

C>В случае бинарного представления можно прочитать с диска только один нужный кластер/страницу памяти.
...
C>Не мерджить, а одновременно писать в один файл.

Так это не вопрос сериализации. То, о чём вы пишите — это база данных. Примитивная, но база. Сериализация — это нечто потоковое, не приспособленное к доступу по индексу.
И каждый день — без права на ошибку...
Re[8]: упаковка float/double
От: Chorkov Россия  
Дата: 11.03.20 14:23
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, Chorkov, Вы писали:


C>>Никого не удивляет, что все форматы хранения видео — бинарные?

BFE>Нет, не удивляет, ведь по сути это одно данное.

Внутрення структура там вполне сравнима по сложности с HTML. (Накопилось закгоды )

C>>Когда понадобится 100499-й снова от начала файла отсчитывать?

C>>В случае бинарного представления можно прочитать с диска только один нужный кластер/страницу памяти.
BFE>...
C>>Не мерджить, а одновременно писать в один файл.

BFE>Так это не вопрос сериализации. То, о чём вы пишите — это база данных. Примитивная, но база. Сериализация — это нечто потоковое, не приспособленное к доступу по индексу.


Но библиотеки для укладки сложно структурированных данных в эту форму массива байтиков, почему-то называются билиотеками сериализации
Re[9]: упаковка float/double
От: B0FEE664  
Дата: 11.03.20 15:41
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>>>Никого не удивляет, что все форматы хранения видео — бинарные?

BFE>>Нет, не удивляет, ведь по сути это одно данное.

C>Внутрення структура там вполне сравнима по сложности с HTML. (Накопилось закгоды )

А ещё данные там сжаты разными хитрыми способами, в наличии проблемы с версиями, к разным версиям нужны разные кодаки, существуют (или существовали) проблемы с падениями при порче потока и вряд ли у вас получится по индексу вписать в такое видео другой кадр. Проблем с поддержанием всего зоопарка хватает. Вы уверены, что не хотите избежать всех этих проблем? Или ваши данные на самом деле занимают такой же объём как видео?

BFE>>Так это не вопрос сериализации. То, о чём вы пишите — это база данных. Примитивная, но база. Сериализация — это нечто потоковое, не приспособленное к доступу по индексу.

C>Но библиотеки для укладки сложно структурированных данных в эту форму массива байтиков, почему-то называются билиотеками сериализации

При сериализации количество и размеры структур обычно заранее не известны. Как при этом можно в них что-то записывать по заданному смещению мне так же не понятно.
И каждый день — без права на ошибку...
Re: упаковка float/double
От: Teolog  
Дата: 11.03.20 16:08
Оценка:
Здравствуйте, niXman, Вы писали:

X>привет!


X>задумался над сабжем.

X>поситал по теме(https://habr.com/ru/post/112953/), но, признаюсь, многого не понял.
X>гугления тоже какие-то бестолковые...

X>может кто расскажет что по теме?


X>подумал, что можно использовать modf() чтоб разбить на части. знак тоже понятно как получить.

X>с интегральной частью вроде все понятно...
X>но как быть с экпонентой? как ее привести к целому? как хранить кол-во нулей?

X>какие мысли?


Мысли такие. Не создавать себе проблем, и использовать готовую библиотеку сериализации типа protobuf.
Для реализации произвольного чтения данные писать большими блоками каждый из которых сериализовать отдельно. Упаковку можно реализовать фоновым потоком на случай если задержки при записи критичны.
Если решаеться задача сохранения бинарного лога с кучей данных, на что похоже, это будет работать адекватно.
Re[2]: упаковка float/double
От: flаt  
Дата: 12.03.20 10:07
Оценка:
Здравствуйте, Teolog, Вы писали:


T>Если решаеться задача сохранения бинарного лога с кучей данных, на что похоже, это будет работать адекватно.


Не совсем. Автором решается задача создать Yet another serialization.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.