Есть задача преобразования float значений в значения типа int (одно float значение в одно int значение) без потери информации, т.е., чтобы потом можно было выполнить обратное преобразование. Как это можно реализовать?
Важно
Надо, чтобы при таком преобразовании сохранялся порядок и сумма,
т.е. для любых a, b: float должно выполняться:
to_float(to_int(a) + to_int(b)) == a + b
to_int(a) < to_int(b) при a < b и т.д.
Нашёл на англоязычном SO ответ, где побитово представляется структура float значений, но не представляю, как её можно применить для своей задачи.
Примечание: NaN и inf в моей задаче преобразовывать не надо.
Попытки решения
Изначально на ум пришла сериализация с помощью pickle.dumps, а затем получение int из этих байт, но это совсем не рациональное решение и оно совершенно не удовлетворяет требованиям.
Были попытки реализовать это через байтовые представления чисел (ответ Qwertiy♦), в таком варианте не сохраняется сумма.
fractions.Fraction(0.1+0.2)=>Fraction(1351079888211149, 4503599627370496)` – vp_arth Oct 26 '20 at 15:38intзначении? И как их потом друг от друга отделять после сложения, например? – Mikhail Murugov Oct 26 '20 at 15:43((0.1+0.2)*1e32).as_integer_ratio()[0] / 1e32 == (0.1+0.2)32 взял «от балды», не в курсе, сколько там точности) – vp_arth Oct 26 '20 at 15:43double(64 бит), вроде как. Идею Вашу понял, сейчас попробую потестировать. – Mikhail Murugov Oct 26 '20 at 15:51sys.float_info.epsilon(не точно, но уже хоть что-то), но порядок не сохраняется :/ Например, для чисел1.043380078e-314, 2.0142355855e-314(в преобразованииe32заменил наe64). – Mikhail Murugov Oct 26 '20 at 16:21(1<<64). Ну да, если вам весь диапазон нужен, такой фокус не пройдёт, знаменатель слишком большой) – vp_arth Oct 26 '20 at 16:45float(Decimal.from_float(1.23e-312)). Хотя, вам нужен именно int... – vp_arth Oct 26 '20 at 17:00