Re[3]: Простейшее форматирование плавающего в строку
От: Videoman Россия https://hts.tv/
Дата: 11.09.19 09:28
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я усомнился, а действительно ли он отбрасывает лишние нули. Ну, допустим, отбрасывает, тогда вопрос, как добиться такого же результата, как при работе с потоками и манипулятором std::fixed — то есть, чтоб нули НЕ отбрасывались?


Я его использую при сериализации и десериализации. На что ругается компилятор?
Re[4]: Простейшее форматирование плавающего в строку
От: rg45 СССР  
Дата: 11.09.19 09:38
Оценка:
Здравствуйте, Videoman, Вы писали:

R>>Я усомнился, а действительно ли он отбрасывает лишние нули. Ну, допустим, отбрасывает, тогда вопрос, как добиться такого же результата, как при работе с потоками и манипулятором std::fixed — то есть, чтоб нули НЕ отбрасывались?


V>Я его использую при сериализации и десериализации. На что ругается компилятор?


Оригинальный пример здесь: https://en.cppreference.com/w/cpp/utility/to_chars
Адаптированный вариант: https://coliru.stacked-crooked.com/view?id=3ba817e3a6e479bf

Сообщение компилятора:
g++ -std=c++2a -pthread  -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors main.cpp -lm  -latomic -lstdc++fs  && ./a.out
main.cpp: In function 'int main()':
main.cpp:12:14: error: 'std::chars_format' has not been declared
   12 |         std::chars_format::fixed, 2);
      |              ^~~~~~~~~~~~
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Простейшее форматирование плавающего в строку
От: Videoman Россия https://hts.tv/
Дата: 11.09.19 10:08
Оценка:
Здравствуйте, 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.

Отредактировано 11.09.2019 10:11 Videoman . Предыдущая версия .
Re[6]: Простейшее форматирование плавающего в строку
От: Videoman Россия https://hts.tv/
Дата: 11.09.19 10:20
Оценка:
Здравствуйте, 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.


P.S. Сорри не обратил внимание что вы на gсс.
Отредактировано 11.09.2019 10:21 Videoman . Предыдущая версия .
Re[6]: Простейшее форматирование плавающего в строку
От: Went  
Дата: 11.09.19 10:24
Оценка:
Здравствуйте, night beast, Вы писали:
NB>а тебе для чего? если для рублей, то лучше в целыми работать..
Для размеров в условных пикселях, которые могут быть и дробными, но редко
Re[2]: Простейшее форматирование плавающего в строку
От: Went  
Дата: 11.09.19 10:25
Оценка:
Здравствуйте, rg45, Вы писали:
R>Может, стоит таки смириться с лишними нулями? Это действительно принципиально, или у тебя чисто спортивный интерес?
Не стоит. Сильно захламляет вывод, потому что в 99% случаях все числа снапнуты к целым и мы работаем как с целыми. Но после некоторых преобразований данные могут стать дробными и пользователь должен это увидеть.
Re: Простейшее форматирование плавающего в строку
От: Went  
Дата: 11.09.19 10:36
Оценка:
Здравствуйте. Раз эта тема вызывала интерес, выложу свое неоптимальное, но простое решение (MFC )
CString rounded_float_to_string(Float value, Int precision)
{
  Float factor = pow(10.0f, precision);
  Int whole = round(value * factor);
  Float fract = whole / factor;
  CString result;
  result.Format("%g", fract);
  return result;
}

Вроде бы на практике работает. Но сваливается в экспоненту на очень больших числах.
Re[7]: Простейшее форматирование плавающего в строку
От: night beast СССР  
Дата: 11.09.19 11:19
Оценка:
Здравствуйте, Went, Вы писали:

NB>>а тебе для чего? если для рублей, то лучше в целыми работать..

W>Для размеров в условных пикселях, которые могут быть и дробными, но редко

думаю фиксед и для пикселей пойдет.
Re[2]: Простейшее форматирование плавающего в строку
От: rg45 СССР  
Дата: 11.09.19 12:37
Оценка: :))
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Раз эта тема вызывала интерес, выложу свое неоптимальное, но простое решение (MFC )


??? MFC ???

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Простейшее форматирование плавающего в строку
От: IID Россия  
Дата: 11.09.19 16:40
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>И что получится, например, при f = 1e+10 ?


1) диапазон не оговаривался
2) если всё-таки надо — можно взять int64_t

kalsarikännit
Re[4]: Простейшее форматирование плавающего в строку
От: rg45 СССР  
Дата: 11.09.19 20:02
Оценка:
Здравствуйте, IID, Вы писали:

R>>И что получится, например, при f = 1e+10 ?


IID>1) диапазон не оговаривался


Вот именно. Мы взяли и самовольно наложили ограничение с каких-то делов. При выводе в стандартные потоки таких ограничений нет, почему у нас должно быть хуже?

IID>2) если всё-таки надо — можно взять int64_t

IID>

Ну вместо 1e+10 напишем 1e+20 и получится то же самое
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.09.2019 20:13 rg45 . Предыдущая версия . Еще …
Отредактировано 11.09.2019 20:07 rg45 . Предыдущая версия .
Re[3]: Простейшее форматирование плавающего в строку
От: c-smile Канада http://terrainformatica.com
Дата: 11.09.19 21:57
Оценка:
Здравствуйте, rg45, Вы писали:

CS>>Как-то так (псевдо код)


CS>>
CS>>int n = int(f * 100);
CS>> . . .
CS>>


R>И что получится, например, при f = 1e+10 ?


Что надо то и получится. Я же написал что это псевдо код. Т.е. тот int может быть int64
в который точно поместится целочисленная мантисса от double (2^52).
Re[5]: Простейшее форматирование плавающего в строку
От: c-smile Канада http://terrainformatica.com
Дата: 11.09.19 22:17
Оценка:
Здравствуйте, rg45, Вы писали:

IID>>2) если всё-таки надо — можно взять int64_t

IID>>

R>Ну вместо 1e+10 напишем 1e+20 и получится то же самое


А что выведет твоя printf функция если ей дать 1e+20 число? Количество зеленых попугаев, а не число ибо все что дальше единиц и после запятой там уже будет случайными числами (в данном контексте).

Т.е. для doubles больше std::numeric_limits<double>::digits10 / 100 исходная задача вообще смысла не имеет. Такие вот, брат, пироги.
Re[6]: Простейшее форматирование плавающего в строку
От: rg45 СССР  
Дата: 12.09.19 05:04
Оценка:
Здравствуйте, c-smile, Вы писали:

R>>Ну вместо 1e+10 напишем 1e+20 и получится то же самое


CS>А что выведет твоя printf функция если ей дать 1e+20 число? Количество зеленых попугаев, а не число ибо все что дальше единиц и после запятой там уже будет случайными числами (в данном контексте).


Выведет ровно то же самое, что выводят стандартные потоки: https://ideone.com/2iDTT4. А главное, она никогда не породит UB.

CS>Т.е. для doubles больше std::numeric_limits<double>::digits10 / 100 исходная задача вообще смысла не имеет. Такие вот, брат, пироги.


Исходная задача
Автор: Went
Дата: 10.09.19
формулировалась так: "Мне нужно превратить стандартными средствами float в строку...". Стандартными, понимаешь? Ни одно из стандартных средств не накладывает никаких ограничений на диапазоны входных значений. Mы вполне можем вывести в стандартный поток и 1е+100, и 1e+300, и получим всего лишь потерю точности, но не UB, и не откровенную белиберду.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 12.09.2019 13:31 rg45 . Предыдущая версия . Еще …
Отредактировано 12.09.2019 12:17 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 7:45 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 7:18 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 7:17 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 7:17 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 6:44 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:52 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:51 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:49 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:47 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:39 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:38 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:36 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:34 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:28 rg45 . Предыдущая версия .
Re[4]: Простейшее форматирование плавающего в строку
От: rg45 СССР  
Дата: 12.09.19 05:07
Оценка:
Здравствуйте, c-smile, Вы писали:


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, вот тогда бы я первый воскликнул "браво!"
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 12.09.2019 13:06 rg45 . Предыдущая версия . Еще …
Отредактировано 12.09.2019 8:41 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 8:34 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 6:16 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 6:02 rg45 . Предыдущая версия .
Отредактировано 12.09.2019 5:58 rg45 . Предыдущая версия .
Re[5]: Простейшее форматирование плавающего в строку
От: c-smile Канада http://terrainformatica.com
Дата: 15.09.19 03:04
Оценка:
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.

Мне кажется что сие очевидно, нет?

На этом, кстати, построена вся целочисленная арифметика JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
Re[6]: Простейшее форматирование плавающего в строку
От: rg45 СССР  
Дата: 15.09.19 08:27
Оценка:
Здравствуйте, c-smile, Вы писали:



CS>А для чисел больше 252 / 100 ( в данном случае) задача вывода цифирей после запятой смысла не имеет по определению — там будут случайные числа.


CS>Мне кажется что сие очевидно, нет?


Это может иметь смысл, когда требуется поведение близкое к поведению стандартных средств форматирования. О чем собственно и спрашивал ТС. В твоих рассуждениях хоть и присутствует здравый смысл, но предлагаемый тобой подход не обеспечивает безопасности получения результата, а перекладывает эту заботу на вызывающий код. Возможно, в каких-то случаях это и приемлемо, но ты решаешь не совсем ту задачу, которую ставил ТС.

P.S. До предлагаемого тобой решения ТС без труда мог бы додуматься и сам, уж поверь мне, как его бывшему коллеге
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 15.09.2019 8:34 rg45 . Предыдущая версия . Еще …
Отредактировано 15.09.2019 8:28 rg45 . Предыдущая версия .
Re: Простейшее форматирование плавающего в строку
От: кт  
Дата: 26.09.19 06:28
Оценка: :)
Здравствуйте, 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;


результат для положительных чисел:

1.0000
отформатировано: 1
4
отформатировано: 4
1.234
отформатировано: 1.23
1234e9
отформатировано: 1234000000000
Re[2]: Упс... и неправильно
От: кт  
Дата: 26.09.19 13:26
Оценка:
Упс… и неправильно, вместо 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;

и нужный результат получается:
3.00
отформатировано: 3
3.10
отформатировано: 3.1
3.11
отформатировано: 3.11
3.1000000000001
отформатировано: 3.1
3.15
отформатировано: 3.15
3.16
отформатировано: 3.16
534534534534.6667
отформатировано: 534534534534.67
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.