Здравствуйте, rg45, Вы писали:
R>Я усомнился, а действительно ли он отбрасывает лишние нули. Ну, допустим, отбрасывает, тогда вопрос, как добиться такого же результата, как при работе с потоками и манипулятором std::fixed — то есть, чтоб нули НЕ отбрасывались?
Я его использую при сериализации и десериализации. На что ругается компилятор?
Re[4]: Простейшее форматирование плавающего в строку
Здравствуйте, Videoman, Вы писали:
R>>Я усомнился, а действительно ли он отбрасывает лишние нули. Ну, допустим, отбрасывает, тогда вопрос, как добиться такого же результата, как при работе с потоками и манипулятором std::fixed — то есть, чтоб нули НЕ отбрасывались?
V>Я его использую при сериализации и десериализации. На что ругается компилятор?
Здравствуйте, rg45, Вы писали:
R>Сообщение компилятора: R>
R>g++ -std=c++2a -pthread -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors main.cpp -lm -latomic -lstdc++fs && ./a.out
R>main.cpp: In function 'int main()':
R>main.cpp:12:14: error: 'std::chars_format' has not been declared
R> 12 | std::chars_format::fixed, 2);
R> | ^~~~~~~~~~~~
R>
Да... в VS 2017 вплоть до версии 15.9.16, to_chars с параметром precision — не реализована, помечена как =delete. Мне как раз нужна была другая реализация, как у автора топика, и я не доглядел насчет precision. Жалко, будем ждать пока Microsoft сподобится все реализовать по стандарту.
charconv from_chars() and to_chars() are available for integers. The timeline for floating-point from_chars() and floating-point to_chars() is as follows:
VS 2017 15.7: Integer from_chars() and to_chars().
VS 2017 15.8: Floating-point from_chars().
VS 2017 15.9: Floating-point to_chars() overloads for shortest decimal.
VS 2019 16.0: Floating-point to_chars() overloads for shortest hex and precision hex.
VS 2019 16.2: Floating-point to_chars() overloads for precision fixed and precision scientific.
Not yet implemented: The floating-point to_chars() overload for precision general.
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, rg45, Вы писали:
R>>Сообщение компилятора: R>>
R>>g++ -std=c++2a -pthread -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors main.cpp -lm -latomic -lstdc++fs && ./a.out
R>>main.cpp: In function 'int main()':
R>>main.cpp:12:14: error: 'std::chars_format' has not been declared
R>> 12 | std::chars_format::fixed, 2);
R>> | ^~~~~~~~~~~~
R>>
V>Да... в VS 2017 вплоть до версии 15.9.16, to_chars с параметром precision — не реализована, помечена как =delete. Мне как раз нужна была другая реализация, как у автора топика, и я не доглядел насчет precision. Жалко, будем ждать пока Microsoft сподобится все реализовать по стандарту. V>
V>charconv from_chars() and to_chars() are available for integers. The timeline for floating-point from_chars() and floating-point to_chars() is as follows:
V>VS 2017 15.7: Integer from_chars() and to_chars().
V>VS 2017 15.8: Floating-point from_chars().
V>VS 2017 15.9: Floating-point to_chars() overloads for shortest decimal.
V>VS 2019 16.0: Floating-point to_chars() overloads for shortest hex and precision hex.
V>VS 2019 16.2: Floating-point to_chars() overloads for precision fixed and precision scientific.
V>Not yet implemented: The floating-point to_chars() overload for precision general.
Здравствуйте, night beast, Вы писали: NB>а тебе для чего? если для рублей, то лучше в целыми работать..
Для размеров в условных пикселях, которые могут быть и дробными, но редко
Re[2]: Простейшее форматирование плавающего в строку
Здравствуйте, rg45, Вы писали: R>Может, стоит таки смириться с лишними нулями? Это действительно принципиально, или у тебя чисто спортивный интерес?
Не стоит. Сильно захламляет вывод, потому что в 99% случаях все числа снапнуты к целым и мы работаем как с целыми. Но после некоторых преобразований данные могут стать дробными и пользователь должен это увидеть.
Здравствуйте, Went, Вы писали:
NB>>а тебе для чего? если для рублей, то лучше в целыми работать.. W>Для размеров в условных пикселях, которые могут быть и дробными, но редко
думаю фиксед и для пикселей пойдет.
Re[2]: Простейшее форматирование плавающего в строку
Здравствуйте, IID, Вы писали:
R>>И что получится, например, при f = 1e+10 ?
IID>1) диапазон не оговаривался
Вот именно. Мы взяли и самовольно наложили ограничение с каких-то делов. При выводе в стандартные потоки таких ограничений нет, почему у нас должно быть хуже?
IID>2) если всё-таки надо — можно взять int64_t IID>
Ну вместо 1e+10 напишем 1e+20 и получится то же самое
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
CS>>Как-то так (псевдо код)
CS>>
CS>>int n = int(f * 100);
CS>> . . .
CS>>
R>И что получится, например, при f = 1e+10 ?
Что надо то и получится. Я же написал что это псевдо код. Т.е. тот int может быть int64
в который точно поместится целочисленная мантисса от double (2^52).
Re[5]: Простейшее форматирование плавающего в строку
Здравствуйте, rg45, Вы писали:
IID>>2) если всё-таки надо — можно взять int64_t IID>>
R>Ну вместо 1e+10 напишем 1e+20 и получится то же самое
А что выведет твоя printf функция если ей дать 1e+20 число? Количество зеленых попугаев, а не число ибо все что дальше единиц и после запятой там уже будет случайными числами (в данном контексте).
Т.е. для doubles больше std::numeric_limits<double>::digits10 / 100 исходная задача вообще смысла не имеет. Такие вот, брат, пироги.
Re[6]: Простейшее форматирование плавающего в строку
Здравствуйте, c-smile, Вы писали:
R>>Ну вместо 1e+10 напишем 1e+20 и получится то же самое
CS>А что выведет твоя printf функция если ей дать 1e+20 число? Количество зеленых попугаев, а не число ибо все что дальше единиц и после запятой там уже будет случайными числами (в данном контексте).
Выведет ровно то же самое, что выводят стандартные потоки: https://ideone.com/2iDTT4. А главное, она никогда не породит UB.
CS>Т.е. для doubles больше std::numeric_limits<double>::digits10 / 100 исходная задача вообще смысла не имеет. Такие вот, брат, пироги.
формулировалась так: "Мне нужно превратить стандартными средствами float в строку...". Стандартными, понимаешь? Ни одно из стандартных средств не накладывает никаких ограничений на диапазоны входных значений. Mы вполне можем вывести в стандартный поток и 1е+100, и 1e+300, и получим всего лишь потерю точности, но не UB, и не откровенную белиберду.
--
Не можешь достичь желаемого — пожелай достигнутого.
R>>И что получится, например, при f = 1e+10 ?
CS>Что надо то и получится. Я же написал что это псевдо код. Т.е. тот int может быть int64 CS>в который точно поместится целочисленная мантисса от double (2^52).
А при чем тут мантисса? Ты же в int загоняешь не мантиссу, а все число. А диапазон покрываемый double на многие порядки шире, чем диапазон, покрываемый int и int64, поэтому на абсолютно подавляющем подмножестве значений double мы получим UB. И замена int на int64 лишь слегка-слегка отодвигает проблему, но не решает ее (только задумайся о разнице между 1е+18 и 1е+308).
P.S. А вот если бы ты действительно поотдельности обработал мантиссу и экспоненциальную часть на целых числах, без UB, вот тогда бы я первый воскликнул "браво!"
--
Не можешь достичь желаемого — пожелай достигнутого.
R>>>И что получится, например, при f = 1e+10 ?
CS>>Что надо то и получится. Я же написал что это псевдо код. Т.е. тот int может быть int64 CS>>в который точно поместится целочисленная мантисса от double (2^52).
R>А при чем тут мантисса? Ты же в int загоняешь не мантиссу, а все число. А диапазон покрываемый double на многие порядки шире, чем диапазон, покрываемый int и int64, поэтому на абсолютно подавляющем подмножестве значений double мы получим UB. И замена int на int64 лишь слегка-слегка отодвигает проблему, но не решает ее (только задумайся о разнице между 1е+18 и 1е+308).
double может хранить целочисленные значения. Но только в том случае если целое число помещается в поле мантиссы (52 бита).
Что есть заведомо меньше чем int64.
А для чисел больше 252 / 100 ( в данном случае) задача вывода цифирей после запятой смысла не имеет по определению — там будут случайные числа.
Т.е. в случае double и int64 мой алгоритм выведет точно то что нужно. Как и в случае float и int32.
CS>А для чисел больше 252 / 100 ( в данном случае) задача вывода цифирей после запятой смысла не имеет по определению — там будут случайные числа.
CS>Мне кажется что сие очевидно, нет?
Это может иметь смысл, когда требуется поведение близкое к поведению стандартных средств форматирования. О чем собственно и спрашивал ТС. В твоих рассуждениях хоть и присутствует здравый смысл, но предлагаемый тобой подход не обеспечивает безопасности получения результата, а перекладывает эту заботу на вызывающий код. Возможно, в каких-то случаях это и приемлемо, но ты решаешь не совсем ту задачу, которую ставил ТС.
P.S. До предлагаемого тобой решения ТС без труда мог бы додуматься и сам, уж поверь мне, как его бывшему коллеге
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Went, Вы писали:
W>Доброго дня. Простите за ламерский вопрос, но все же
В названии «простейший» кроется подвох: по заданию требуется искать замыкающий ноль, а это в стандартах, как правило, не предусмотрено. О чем здесь и говорили. И я так понял, что лишние пробелы не нужны (иначе, зачем нужно убирать замыкающий ноль?)
Тогда прямо по заветам Д.Ритчи: «если тебе нужен PL/1, ты знаешь, где его взять»
test_format:proc main;
dcl s char(*) var, x float(53);
do repeat;
get list(x);
if x -trunc(x+0.5e0) <5e-3 then put string(s) edit(x)(f(15)); else
if x*10e0-trunc(x*10e0+0.5e0)<5e-2 then put string(s) edit(x)(f(15,1)); else
put string(s) edit(x)(f(15,2));
put list('отформатировано:',trim(s));
put skip;
end repeat;
end test_format;
Упс… и неправильно, вместо 3.16 пишет не то,
тогда вот так:
test_format:proc main;
dcl s char(*) var, x float(53);
do repeat;
get list(x);
if x -trunc(x) <5e-3 then put string(s) edit(x)(f(15)); else
if x -trunc(x) >0.99e0 then put string(s) edit(x)(f(15)); else
if x*10-trunc(x*10)<5e-2 then put string(s) edit(x)(f(15,1)); else
if x*10-trunc(x*10)>0.99e0 then put string(s) edit(x)(f(15,1)); else
put string(s) edit(x)(f(15,2));
put list('отформатировано:',trim(s));
put skip;
end repeat;
end test_format;