Fixed-point to string
От: cppguard  
Дата: 30.08.23 22:51
Оценка:
Накидал тут на коленке код для вывода вещественных чисел с фиксированной запятой в привычном виде. Вышло как-то слишком просто. Имеет право на жизнь?
#include <iostream>

template<typename T, unsigned N>
class Q {
    T value;
public:
    Q(T value): value(value) {}
    T integral() const { return value >> N; }
    T fractional() const { return value & (1 << N - 1); }
};

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

template<unsigned Multiplier>
struct FractToString<0, Multiplier> {
    static unsigned value(unsigned value, unsigned acc) {
        return acc;
    }
};


template<typename T, unsigned N>
std::ostream& operator<< (std::ostream&  os, const Q<T, N>& q)
{
    return os << static_cast<int>(q.integral()) << "." << static_cast<int>(FractToString<N>::value(q.fractional()));
}


int main(int argc, char *argv[]) {
    std::cout << Q<uint8_t, 3>(0b101101) << std::endl;
}
Re: Fixed-point to string
От: CreatorCray  
Дата: 30.08.23 23:35
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Вышло как-то слишком просто.

Просто?

C> Имеет право на жизнь?

Покажи как оно выведет аналог 1.001
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Re[2]: Fixed-point to string
От: cppguard  
Дата: 30.08.23 23:43
Оценка: :)
Здравствуйте, CreatorCray, Вы писали:


C>>fixed-point

CC>1.001

Так и запишем — матчасть не выучил
Re[3]: Fixed-point to string
От: CreatorCray  
Дата: 31.08.23 02:13
Оценка:
Здравствуйте, cppguard, Вы писали:

C>>>fixed-point

CC>>аналог 1.001

C>Так и запишем — матчасть не выучил


Я на fixed point рендерер на асме написал в середине 90х.
Ты же походу и читать не умеешь и матчасть совершенно не знаешь, раз вообще не понял про что была речь.
Ну да ладно.

Начнём по порядку:
1. Что оно выведет для Q<uint8_t, 3> ((2 << 3) + 1) и что должно было вывести?
3. Что оно выведет для Q<uint32_t, 8> ((2 << 8) + 1) и что должно было вывести?
2. Что оно выведет для Q<uint32_t, 16> ((2 << 16) + 1) и что должно было вывести?

  спойлеры
1. Выводит 2.0 вместо 2.125. В коде довольно очевидный баг.
2. Выводит (после исправления бага) 2.390625 вместо 2.00390625 ибо ведушие нули протерялись при выводе целого
3. Выводит феерическое 2.-2030932031 вместо 2.0000152587890625 ибо acc переполняется а потом ты это ещё и в signed кастишь, ну и нули протеряны всё равно
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Re: Fixed-point to string
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 31.08.23 05:50
Оценка:
Здравствуйте, cppguard, Вы писали:

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


Не очень, мягко говоря

Фиксированная точка (запятая) полезна в первую очередь для бухгалтерии/финансов, а там все числа принудительно десятичные. У тебя же рассчитано на двоичку. Я просто не могу себе представить домен, для которого такое нужно. Если какие-нибудь ситуации типа "с датчика снимаем 10 двоичных цифр дробной части ибо АЦП", то для таких лучше форматировать в шестнадцатиричную — типа значение "0x23.fc", а не в десятичную.
Но это особые ситуации и для них вообще неизвестно, стоит ли так стараться.

А для десятичной точки тебе нужно деление на 10**N чтобы нормально отображать. Вот тут можно средствами C++ догнать это до константных операций (деление на константу через обратное умножение).

Про ошибки в коде тебе сказали, а как общий принцип — тесты и ещё раз тесты! Задача такая, что сделать ошибку тривиально. Поэтому все и основные, и маргинальные случаи — подкрепить тестами.
The God is real, unless declared integer.
Re[4]: Fixed-point to string
От: cppguard  
Дата: 31.08.23 06:33
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Ты же походу и читать не умеешь и матчасть совершенно не знаешь, раз вообще не понял про что была речь.

CC>Ну да ладно.
1.001 непредставимо в виде двоичной дроби. О чём речь? Или вопрос был про 0b1001?

CC>
  спойлеры
CC>1. Выводит 2.0 вместо 2.125. В коде довольно очевидный баг.
CC>2. Выводит (после исправления бага) 2.390625 вместо 2.00390625 ибо ведушие нули протерялись при выводе целого
CC>3. Выводит феерическое 2.-2030932031 вместо 2.0000152587890625 ибо acc переполняется а потом ты это ещё и в signed кастишь, ну и нули протеряны всё равно


За тестирование спасибо. Насчёт переполнения — предполагается работа только с uint8_t и форматами чисел Q4.4 и Q1.7, остальное не интересует, поэтому я и не особо старался.
Re[2]: Fixed-point to string
От: cppguard  
Дата: 31.08.23 06:38
Оценка:
Здравствуйте, netch80, Вы писали:

N>Фиксированная точка (запятая) полезна в первую очередь для бухгалтерии/финансов, а там все числа принудительно десятичные. У тебя же рассчитано на двоичку. Я просто не могу себе представить домен, для которого такое нужно. Если какие-нибудь ситуации типа "с датчика снимаем 10 двоичных цифр дробной части ибо АЦП", то для таких лучше форматировать в шестнадцатиричную — типа значение "0x23.fc", а не в десятичную.

Это нужно для отладки математики с фиксированной точкой на микроконтроллерах с аппаратным умножением.

N>Про ошибки в коде тебе сказали, а как общий принцип — тесты и ещё раз тесты! Задача такая, что сделать ошибку тривиально. Поэтому все и основные, и маргинальные случаи — подкрепить тестами.

Хорошо, но вопрос не об этом был. Если исправить ошибку, то код работает, но при этом он довольно компактен. А если загуглить "fixed-point number to string", то находятся какие-то монстры. Поскольку я не считаю себя мега-гуру, то решил спросить у сообщества — правильно ли я делаю.
Re[3]: Fixed-point to string
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 31.08.23 07:43
Оценка:
Здравствуйте, cppguard, Вы писали:

N>>Фиксированная точка (запятая) полезна в первую очередь для бухгалтерии/финансов, а там все числа принудительно десятичные. У тебя же рассчитано на двоичку. Я просто не могу себе представить домен, для которого такое нужно. Если какие-нибудь ситуации типа "с датчика снимаем 10 двоичных цифр дробной части ибо АЦП", то для таких лучше форматировать в шестнадцатиричную — типа значение "0x23.fc", а не в десятичную.

C>Это нужно для отладки математики с фиксированной точкой на микроконтроллерах с аппаратным умножением.

Тогда да, особый случай.
Ну точно надо в hex всё вводить и выводить. В крайнем случае в чистой двоичке.
Но не в десятичке, со всеми этими 0.0009765625 ты повесишься быстрее, чем отладишь.

N>>Про ошибки в коде тебе сказали, а как общий принцип — тесты и ещё раз тесты! Задача такая, что сделать ошибку тривиально. Поэтому все и основные, и маргинальные случаи — подкрепить тестами.

C>Хорошо, но вопрос не об этом был. Если исправить ошибку, то код работает, но при этом он довольно компактен. А если загуглить "fixed-point number to string", то находятся какие-то монстры. Поскольку я не считаю себя мега-гуру, то решил спросить у сообщества — правильно ли я делаю.

Я думаю, потому и монстры, что они десятичные. А у тебя другая цель.
The God is real, unless declared integer.
Re[5]: Fixed-point to string
От: T4r4sB Россия  
Дата: 31.08.23 08:41
Оценка:
Здравствуйте, cppguard, Вы писали:


C>1.001 непредставимо в виде двоичной дроби. О чём речь? Или вопрос был про 0b1001?


В виде double оно тоже не представимо но это не мешает им пользоваться.
Очевидно речь шла про ближайшее приближение к этому числу
Re[6]: Fixed-point to string
От: cppguard  
Дата: 31.08.23 09:11
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>В виде double оно тоже не представимо но это не мешает им пользоваться.

TB>Очевидно речь шла про ближайшее приближение к этому числу

Вообще не очевидно. Ближайшее с какой стороны? Для fixed-point неопределены всякие epsilon и так далее. Да и процедуру конвертации я не приводил, чтобы давать такой тест. К чему вообще этот вопрос был?
Re[4]: Fixed-point to string
От: cppguard  
Дата: 31.08.23 09:16
Оценка:
Здравствуйте, netch80, Вы писали:

N>Тогда да, особый случай.

N>Ну точно надо в hex всё вводить и выводить. В крайнем случае в чистой двоичке.
N>Но не в десятичке, со всеми этими 0.0009765625 ты повесишься быстрее, чем отладишь.

Вот взять реальный пример. Есть даные магнитометра — XYZ, нужно перевести эти значения в углы Эйлера. Математика вся с фиксированной точкой, и глазами отлаживать удобно, смотря именно на десятичные значения, потому что в голове идёт привязка к радианам. Я уверен, что это лишь вопрос надроча, но для себя я пока не представляю отладку математики в шеснадцатеричных значениях.
Re: Fixed-point to string
От: SaZ  
Дата: 31.08.23 10:21
Оценка:
Здравствуйте, cppguard, Вы писали:

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

C>...

std::format пробовали?
Re[5]: Fixed-point to string
От: пффф  
Дата: 31.08.23 10:31
Оценка: +1
Здравствуйте, cppguard, Вы писали:

C>Вот взять реальный пример. Есть даные магнитометра — XYZ, нужно перевести эти значения в углы Эйлера. Математика вся с фиксированной точкой, и глазами отлаживать удобно, смотря именно на десятичные значения, потому что в голове идёт привязка к радианам. Я уверен, что это лишь вопрос надроча, но для себя я пока не представляю отладку математики в шеснадцатеричных значениях.


Для отладки чтобы глазами смотреть — конвертим во float, печатаем sprintf'ом
Re[7]: Fixed-point to string
От: T4r4sB Россия  
Дата: 31.08.23 10:50
Оценка:
Здравствуйте, cppguard

C>Вообще не очевидно. Ближайшее с какой стороны? Для fixed-point неопределены всякие epsilon и так далее.


Для дабла все то же самое, и?
Re[8]: Fixed-point to string
От: cppguard  
Дата: 31.08.23 11:20
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Для дабла все то же самое, и?


Что я должен ответить? Для моих задач писать процедуру преобразования из обыкновенной десятичной дроби в fixed-point нецелесообразоно от слова совсем, поэтому я не знаю, как 1.001 будет выглядеть в формате Q4.4.
Re[2]: Fixed-point to string
От: T4r4sB Россия  
Дата: 31.08.23 11:40
Оценка:
Здравствуйте, netch80, Вы писали:

N>Фиксированная точка (запятая) полезна в первую очередь для бухгалтерии/финансов, а там все числа принудительно десятичные. У тебя же рассчитано на двоичку. Я просто не могу себе представить домен, для которого такое нужно. Если какие-нибудь ситуации типа "с датчика снимаем 10 двоичных цифр дробной части ибо АЦП", то для таких лучше форматировать в шестнадцатиричную — типа значение "0x23.fc", а не в десятичную.

N>Но это особые ситуации и для них вообще неизвестно, стоит ли так стараться.


Я на полном серьезе использовал фиксированную точку в играх.
Причины две:
1. На моих железках она работала быстрее плавучки, особенно если учесть операции округления
2. Гарантированное воспроизведение результата на любой машине. Для реализации демок/реплеев важно. Я даже сетевой код на этом обосновывал — передавать по сети только команды игрока, а дальше оба компа по ним одинаково воспроизведут изменения в игровом мире, без единого бита рассинхрона
Re[5]: Fixed-point to string
От: B0FEE664  
Дата: 31.08.23 14:26
Оценка:
Здравствуйте, cppguard, Вы писали:

C>За тестирование спасибо. Насчёт переполнения — предполагается работа только с uint8_t и форматами чисел Q4.4 и Q1.7, остальное не интересует, поэтому я и не особо старался.

Я правильно понимаю, что:
Q4.4 — это две таблицы по 16 элементов.
Q1.7 — это 0 или 1 и таблица на 128 элементов.
?
И каждый день — без права на ошибку...
Re[3]: Fixed-point to string
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 31.08.23 14:48
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Я на полном серьезе использовал фиксированную точку в играх.

TB>Причины две:
TB>1. На моих железках она работала быстрее плавучки, особенно если учесть операции округления

ok, возможно.

TB>2. Гарантированное воспроизведение результата на любой машине. Для реализации демок/реплеев важно. Я даже сетевой код на этом обосновывал — передавать по сети только команды игрока, а дальше оба компа по ним одинаково воспроизведут изменения в игровом мире, без единого бита рассинхрона


Вот тут... в пределах корректных операций IEEE754 простые операции (арифметика плюс какой-нибудь sqrt) должны считаться везде одинаково, расхождения должны начаться где-то с sin, log* и дальше в трансцедентные функции. И то насчёт sin не уверен.
Хотя, если где-то тупые реализации, ХЗ...
Но это значит что вы сделали свои реализации — пусть с погрешностями, но одинаковые.
The God is real, unless declared integer.
Re[4]: Fixed-point to string
От: T4r4sB Россия  
Дата: 31.08.23 14:58
Оценка:
Здравствуйте, netch80, Вы писали:

N>Вот тут... в пределах корректных операций IEEE754 простые операции (арифметика плюс какой-нибудь sqrt) должны считаться везде одинаково, расхождения должны начаться где-то с sin, log* и дальше в трансцедентные функции. И то насчёт sin не уверен.

N>Хотя, если где-то тупые реализации, ХЗ...
N>Но это значит что вы сделали свои реализации — пусть с погрешностями, но одинаковые.


А вот хрен. Расхождения зависят не только от режима компиляции.
Даже одна и та же формула в разных контекстах может выдать разный результат на одних входных данных.
Так что не доверяй плавучке
Re: Fixed-point to string
От: Maniacal Россия  
Дата: 31.08.23 15:07
Оценка:
Здравствуйте, cppguard, Вы писали:

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


fcvt можно использовать, там можно указывать сколько цифр после запятой обрабатывать. Только функция точку в строку не пишет, но честно возвращает, где она должна стоять. Так что дополнительные телодвижения нужны, чтобы её туда вертать взад.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.