Я должен представить IEEE 754-1985 дважды (64-разрядное) число с плавающей точкой в человекочитаемой текстовой форме с условием, что текстовая форма может быть проанализирована назад в точно то же (поразрядное) число.
Действительно ли это возможно/практично обойтись без просто печати необработанных байтов? Если бы да, код, чтобы сделать это очень ценилось бы.
Лучший вариант: используйте шестнадцатеричный формат с плавающей запятой C99:
printf("%a", someDouble);
Созданные таким образом строки можно преобразовать обратно в double
с помощью функции C99 strtod ()
, а также с помощью функции scanf ()
. Несколько других языков также поддерживают этот формат. Некоторые примеры:
decimal number %a format meaning
--------------------------------------------
2.0 0x1.0p1 1.0 * 2^1
0.75 0x1.8p-1 1.5 * 2^-1
Шестнадцатеричный формат имеет то преимущество, что все представления точны . Таким образом, преобразование строки обратно в число с плавающей запятой всегда будет давать исходное число, даже если кто-то изменит режим округления, в котором выполняется преобразование. Это неверно для неточных форматов.
Если вы не хотите использовать шестнадцатеричный формат по какой-либо причине и готовы предполагать, что режим округления всегда будет округляться до ближайшего (по умолчанию), тогда вы можете отформатировать свои данные как десятичные с помощью не менее 17 значащих цифр. Если у вас есть процедура преобразования с правильным округлением (у большинства, но не у всех платформ), это гарантирует, что вы сможете выполнить обход от двойного к строковому и обратно без какой-либо потери точности.
В .NET framework для этого есть двусторонний формат:
string formatted = myDouble.ToString("r");
Из документации:
round- Спецификатор поездки гарантирует, что числовое значение , преобразованное в строку , будет преобразовано обратно в то же числовое значение . Когда числовое значение форматируется с использованием этого спецификатора, оно сначала тестируется с использованием общего формата с 15 точками точности для двойного и 7 пробелов. точности для Single. Если значение успешно преобразовано обратно в то же числовое значение, оно форматируется с использованием общего спецификатора формата . Однако, если значение не было успешно преобразовано обратно в то же числовое значение, тогда значение форматируется с использованием 17 цифр точности для Double и 9 цифр точности для Single.
Этот метод, конечно, можно воссоздать практически на любом языке.
Похоже, вы хотите Алгоритм Бургера (PDF):
В режиме свободного формата алгоритм генерирует {{1} } кратчайшая правильно округленная выходная строка, которая преобразуется в то же число при повторном считывании, независимо от того, как средство чтения разрывает связи при округлении.
Также доступен пример исходного кода (на C и схеме).
Это алгоритм, используемый в Python 3.x для обеспечения возможности преобразования чисел с плавающей запятой
в строки и обратно без потери точности. В Python 2.x float
s всегда были представлены 17 значащими цифрами, потому что:
repr (float)
производит 17 значащих цифр, потому что оказывается, что этого достаточно (на большинстве машин), чтобыeval (repr (x)) == x
точно для всех конечных чисел с плавающей запятойx
, но округления до 16 цифр недостаточно, чтобы сделать это верным. (Источник: http://docs.python.org/tutorial/floatingpoint.html )
Да, это можно сделать, хотя реализация зависит от языка. Основная идея заключается в том, чтобы просто вывести его с достаточной точностью.
Обратите внимание, что обратное не верно: некоторые числа, которые могут быть точно представлены в десятичной системе счисления, просто не могут быть представлены в двоичной.