Re: Fixed-point to string
От: fk0 Россия https://fk0.name
Дата: 28.09.23 07:44
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Накидал тут на коленке код для вывода вещественных чисел с фиксированной запятой в привычном виде. Вышло как-то слишком просто. Имеет право на жизнь?


Если вместо велосипеда есть немного более сложная конструкция из библиотечных функций -- следует выбирать последнюю.
Он в отличие от велосипеда как правило не содержит неожиданных сюрпризов и легко узнаваема другими программистами.

C>template<typename T, unsigned N>

C>class Q {
C> T value;
C>public:
C> Q(T value): value(value) {}
C> T integral() const { return value >> N; }
C> T fractional() const { return value & (1 << N — 1); }
C>};

Вот здесь 1 — это int, а sizeof(value) может быть меньше чем sizeof(intmax_t).

А что если N задали нулевым? Можно же!

А что если value -- знаковое. Сдвиг вправо может быть с сохранением знака.
А может быть без.

C>template<unsigned Position, unsigned Multiplier = 5>

C>struct FractToString {
C> static unsigned value(unsigned value, unsigned acc = 0) {
C> auto d = (value >> (Position — 1) & 1) * Multiplier;
C> return FractToString<Position — 1, Multiplier * 5>::value(value, acc * 10 + d);
C> }
C>};

Такой параметр шаблона по-умолчанию -- источник ошибок.

Опять же Position = 0 и UB.

Почему пятёрка захардкожена, что она значит?

Может быть переполнение в acc. Вообще непонятно зачем здесь какие-то рекурсивные вычисления,
по-моему всё сводится к одной линейной арифметической операции и отправке числа в ostream/snprintf/std::format.

Вообще для ввода-вывода (где перформанс не критичен) не зазорно сконвертировать в double.
Если конечно эти фиксированные числа туда влазят.

Вообще почему именно "числа с фиксированной точкой", а не рационалные дроби? Кажется не нужна эта
фиксированная точка вовсе. Проще тупо считать всегда в целых, домножив всё на некий коэффициент K
чтоб значения не утонули в шумах квантизации. А потом при выводе обратно поделить на K. В принципе
число с фиксированной точкой это оно и есть, только там K -- обязательно 2^N. Но это же совершенно
не обязательно. Хотя и удобно для быстрого деления. Но давно уже не обязательно: современные процессоры
уж точно наверняка имеют быстрый умножитель, с помощью которого деление или умножение на константу
делается быстро.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.