Помогите написать функцию show(), которая работает следующим образом.
Если n isnan, то просто вывод Traits::nan
Если n плюс бесконечность, то просто вывод Traits::inf
Если n минус бесконечность, то просто вывод Traits::inf_
Если n 0, то просто вывод Traits::zero
* Если n < 10000 && n >= 0.001, то выводит обычным образом (без 'e')
* Иначе выводит один знак до точки, а всё остальное после точки и печатает e[+/-]NNN (напр: 1.234e+7 7.0e-9_)
* При этом учитывает параметры Traits::show_sign
* Для Traits::always_show_dot == true приписывает ".0", если точку ещё не вывели (это до 'e' когда есть)
* Для отрицательных конечных чисел вконце выводит Traits::negative_ending
Выводит все хранимые цифры без округления (макс точность).
И чтобы я мог заменить: using real = double; на: using real = long double; в дальнейшем, если захочу.
Заранее спасибо.
Здравствуйте, Sm0ke, Вы писали:
S>Выводит все хранимые цифры без округления (макс точность).
Насколько я понимаю, это возможно для вывода в формате использующим основание исчисления кратное двум. Так что в десятичном виде не получится.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Sm0ke, Вы писали:
S>>Выводит все хранимые цифры без округления (макс точность). BFE>Насколько я понимаю, это возможно для вывода в формате использующим основание исчисления кратное двум. Так что в десятичном виде не получится.
Любую конечную двоичную дробь можно записать в виде конечной десятичной дроби. То есть возможно вывести в десятичном виде любое конечное значение, сохранённое в IEEE754 float, double и т.п. Другое дело, что такая запись может получится длинной: может потребоваться столько же десятичных цифр, сколько было двоичных в оригинальной дроби.
Это в обратную сторону возникают проблемы (например, с числом 0.3, которое непредставимо в виде конечной двоичной дроби).
Кстати, практичные библиотеки часто не выводят полную десятичную дробь. А останавливаются когда уже выведенное десятичное значение оказывается самым ближним к выводимому floating-point числу среди всех floating-point чисел, представимых в заданном типе.
То есть условный FloatToString выводит минимальную по длине строку, для которой начинает выполнятся StringToFloat(FloatToString(x)) == x. Так десятичная дробь хотя и оказывается формально не равной исходному числу, но при чтении однозначно превращается в него обратно, так как длинный хвост младших десятичных разрядов всё равно не представим в исходном double или float. И поэтому для целей конвертации потери точности не происходит, а длина записи получается значительно короче.
Здравствуйте, watchmaker, Вы писали:
W>Любую конечную двоичную дробь можно записать в виде конечной десятичной дроби. То есть возможно вывести в десятичном виде любое конечное значение, сохранённое в IEEE754 float, double и т.п. Другое дело, что такая запись может получится длинной: может потребоваться столько же десятичных цифр, сколько было двоичных в оригинальной дроби.
Действительно: конечная сумма двоек возведённых в отрицательную степень всегда имеет конечное представление в десятичной записи. Почему-то я об этом не думал никогда...
W>Кстати, практичные библиотеки часто не выводят полную десятичную дробь. А останавливаются когда уже выведенное десятичное значение оказывается самым ближним к выводимому floating-point числу среди всех floating-point чисел, представимых в заданном типе. W>То есть условный FloatToString выводит минимальную по длине строку, для которой начинает выполнятся StringToFloat(FloatToString(x)) == x. Так десятичная дробь хотя и оказывается формально не равной исходному числу, но при чтении однозначно превращается в него обратно, так как длинный хвост младших десятичных разрядов всё равно не представим в исходном double или float. И поэтому для целей конвертации потери точности не происходит, а длина записи получается значительно короче.
Я правильно понимаю, что стандартных средств для этого такого вывода (без потери точности) в С/С++ нет?
W>>То есть условный FloatToString выводит минимальную по длине строку, для которой начинает выполнятся StringToFloat(FloatToString(x)) == x. Так десятичная дробь хотя и оказывается формально не равной исходному числу, но при чтении однозначно превращается в него обратно, так как длинный хвост младших десятичных разрядов всё равно не представим в исходном double или float. И поэтому для целей конвертации потери точности не происходит, а длина записи получается значительно короче.
BFE>Я правильно понимаю, что стандартных средств для этого такого вывода (без потери точности) в С/С++ нет?
Так в том и дело, что нет потери точности
Ну или скорее нужно сказать, что в разных контекстах под этим подразумевается разное.
То есть в описании какого-нибудь to_chars сказано, что выводимая строка по умолчанию будет самой короткой, которая будет допускать однозначное восстановление исходного числа. Если исходное значение восстанавливается точно, то значит и потери точности нет. Так что тут всё хорошо.
В какой-то другой задаче это может быть не так, и там нужно получать длинную строку. Но это уже другая задача.
А если хочешь получить длинную запись, то, конечно, никто тебя не ограничивает в возможности указать и получить свои 54 значащих цифры для double, явно передав нужное число в условный sprintf. Только это может оказаться примером ложной точности: цифр много, но при этом последние ⅔ из них ни на что не влияют — если их изменить и прочитать обратно double, то на результат это никак не повлияет.
Но стандартный способ есть.
Здравствуйте, B0FEE664, Вы писали:
BFE>Я правильно понимаю, что стандартных средств для этого такого вывода (без потери точности) в С/С++ нет?
В fortran для решения этой проблемы используется шестнадцатеричное представление с плавающей точкой. Но как-то не стало популярным в других языках. Хотя, если решается задачи сериализации в текстовый формат, без требования человеко-читаемости, то это простой в реализации вариант.
Здравствуйте, Chorkov, Вы писали:
BFE>>Я правильно понимаю, что стандартных средств для этого такого вывода (без потери точности) в С/С++ нет? C>В fortran для решения этой проблемы используется шестнадцатеричное представление с плавающей точкой. Но как-то не стало популярным в других языках. Хотя, если решается задачи сериализации в текстовый формат, без требования человеко-читаемости, то это простой в реализации вариант.
Да, два года назад мне так и посоветовали делать:
printf("The pi = %a\n", pi);
однако интересен именно десятичный формат, мне std::to_chars пока не доступен, впрочем и задача не актуальна для меня.