Pull to refresh

Comments 26

template <uint8_t FractionLength>
const FixedPoint<FractionLength> operator - (int l, const FixedPoint<FractionLength>& r)
{
    return r - FixedPoint<FractionLength>(l);
}

Вычитание так не работает

упс, копи-паст forever, спасибо, поправлю у себя, когда буду писать след статью с нормальной имплементацией это там будет

https://github.com/MikeLankamp/fpm

https://github.com/mizvekov/fp

https://github.com/Pharap/FixedPointsArduino

Не благодарите

Посмотреть уже написанный код, совсем ни то же самое, что написать самому )

Если брать существующие целые типы и просто масштабировать значения, типа хранить значения, умноженные на 10000 или на 2^8 или сколько нужно - то разве нельзя обойтись существующими возможностями компилятора? Объявить только отдельный тип чтобы случайно не сложить масштабированное значение с не масштабированным и всё? Тут, конечно, нужно еще понимать для чего всё это делается.

Не очень понял вопрос: я и обошёлся возможностями компилятора

Фрагменты одного из конструкторов:

    explicit FixedPoint(int decimal, unsigned int fraction = 0): val(0)
    {
...
        int8_t sign = decimal > 0 ? +1 : -1;
...
        val |= (decimal << FractionLength);

Из кода очевидно, что decimal может быть отрицательным.

В последней строке фрагмента кода, процитированного мной, написано:

        val |= (decimal << FractionLength);

Built-in bitwise shift operators:

For negative a, the behavior of a << b is undefined.

Соответственно, если конструктор будет вызван с отрицательным decimal, то случится UB.

Вы правы, проглядел, как я уже сказал тестового покрытия нет

Вы правы, проглядел, как я уже сказал тестового покрытия нет

Тестами такое, как правило, не ловится.
Чтобы это поймать тестами, нужно гонять на платформе, где проявление UB будет отличаться от ожидаемого поведения.

В целом, это пока идея, концепция, если хотите, над настоящей реализацией ещё работаю, тут причем я явно перемудрил в паре мест

А сейчас там "имлементация".
Чтобы понять, в чём суть, необходимо внимательно глазами побуквенно проследить.

Досадная опечатка, я не специально

Утверждение: автор может редактировать статью после ее публикации. Считаю, стоит воспользоваться этой возможностью.

утверждение считаем доказанным

constexpr uint8_t mask(uint8_t num)
{
    return (1 << num) - 1;
}

И вообще, рекурсия - это красиво, но для таких примитивных действий (в т.ч. возведение в степень) лучше её не применять. Не забывайте, что это приводит к многократному вызову функции со всеми вытекающими последствиями.

В принципе да, но это constexpr- надеюсь, что компилятор это развернёт в момент компиляции

Если num всегда будет константой, то это операцию лучше делать дефайном, а ещё лучше по месту вставить ((1<<num)-1). Но наличие функции предполагает, что numможетбыть переменной. И тогда приплыли.

лучше поплаваем, чем макросы

Фанатизм тоже ни к чему хорошему не приводит.

Я тут вспомнил, что во второй части статьи нету вызова mask с переменной времени исполнения

Библиотека хороша лишь как гимнастика ума, для практических целей применить её не получится. Хотя бы потому, что вам сразу же понадобится умножать числа с разными порядками, а здесь это не предусмотрено. Во-вторых, при таком умножении только пользователь должен решить какой должен быть порядок у результата. Т.е. чем пожертвовать: целой или дробной частью. А значит оператор для этого не годится, даже friend operator* (...). Нужна отдельная функция, в которую придётся передавать не только операнды, но и порядок результата.

Я с вами частично согласен: библиотека игрушечная, но это можно было бы преодолеть несколькими способами (самый очевидный реализовать длинную арифметику, например над 256 разрядными числами и выдать по 128 разрядов на целую и дробную части). В таком дизайне сохранять слишком маленькие дроби никак не получится т.к. цена младшего разряда фиксирована и равна 2^(-FractionLength)

В десктопных приложениях никто такие библиотеки в здравом уме применять не будет, там используют double не задумываясь. Единственное применение подобных библиотек - это микроконтроллеры, но там заводить по 256 бит на каждую переменную - это непозволительная расточительность.

Конечно нет, в принципе вообще можно целое приложение написать без double кстати говоря, в том смысле, что они не понадобяся, будут строки и инты

Sign up to leave a comment.

Articles