Здравствуйте, fk0, Вы писали:
fk0>Здравствуйте, cppguard, Вы писали:
fk0> Сдвигая единицу влево на сколько угодно, она так и остаётся интом.
fk0>Если инт 32-битный, то сдвигать на 62 влево бессмысленно -- UB.
fk0>А сдвиг инта на 63 тоже UB ибо знаковый...
Ок, я понял идею. Для целевой платформы изпользовать что-то кроме uint8_t не имеет смысла, потому что аппаратное умножение фиксированной точки есть только для однобайтных чисел.
fk0> Можно хотя бы статик ассерт написать. Чтоб не ловить потом UB в продакшене.
fk0>Потому, что ноль туда может прийти неочевидным образом.
fk0>Можно хотя бы enable_if написать и/или static_assert опять же.
Minimal reproducible example.
fk0> Интерфейсы должны быть очевидные и по-возможности не допустать неправильного использования.
fk0>В том числе неявным образом. Потому, что шаблон могут передать в другой шаблон и там инстанцировать
fk0>с третьим шаблоном и всё это может быть сделано из макроса. И на каждом этапе вроде очевидно, а потом
fk0>нашла коса на камень. И гораздо лучше если оно не компилируется сразу, чем потом глючит.
Ну, не работает это в С++. Я могу с полпинка сломать STL, передав неправильный параметр шаблону. Инструменты нужно использовать с умом, а не бить молотком по пальцу и ругаться, что больно. Из-за вот этой вот нездоровой гонки за мнимой типобезопасностью в С++ язык стал такой уровдливый и неповоротливий — UB на каждый чих.
fk0> Любое волшебное число в коде, кроме 1, 0, 1000, 1000000 и т.п. -- источник ошибок.
fk0>И на код ревью сразу нужно спрашивать, почему именно 5, а не 42. Что это значит.
fk0>И если это что-то значит, то может быть стоит завести именнованную константу с этим числом.
Это просто тупо и попахивает слепым следованием "священным заветам". Pi — тоже константа, предложишь и её сделать какой-то именованой? Типа не Pi, а HalfAroundCircleInUnitsThatCorrespondToDegreesWithMultiplier57? В данном случае 5 это константа, которая выводится после оптимизации алгоритма вывода числа. Как её ещё можно назвать кроме как "множитель"?
fk0> Это не принципиально, если только где-то не распечатываются гигабайты строк в секунду.
Это принципиально, если на каждый цикл нужно выводить число на экран. Речь про embedded, тут нельзя написать тысячу строк, загрузив ЦП на пару секунд, и сказать, что наш super-senior software donnut eater так видит.
fk0> 1. целочисленные;
fk0> 2. плавающая точка;
fk0> 3. целочисленные вычисления с неограниченной разрядностью
fk0> (библиотеки bignum и т.п., обычно криптография, бухгалтерия с числами в ASCII);
fk0> 4. экзотические системы счисления: фиббоначиева, логарифмическая и т.п.
fk0>Если вообще
fk0>кому-то эта точка нужна. Можно просто оперировать всегда целыми числами домноженными в голове на K и забыть
fk0>про точку.
fk0> Обычно рациональные числа идут в комплекте с bignum, так что переполнения там нет. Только для практических
fk0>задач оно бессмысленно: для криптографии все операции по-модулю, для научно-технических задач плавающая
fk0>точка подходит лучше. А в бухгалтерии таких денег никто не видел.
Сам предложил рациональные числа, сам ответил, что из-за bignum не имеет смысла их использовать
fk0> И кстати, плавающая точка может оказаться БЫСТРЕЙ фиксированной точки. И часто оказывается.
fk0>Могу рассказать историю, как я заморачивался с вычислениями с фиксированной точкой на микроконтроллере.
fk0>С теми же соображениями. Но в 16 бит не влезает ничего толком, значит надо 32. И потом оказалось, что
fk0>32-битное целочисленное решение тот же алгоритм считает МЕДЛЕНЕЙ, чем с программной реализацией операций
fk0>с плавающей точкой. Как так? Да просто: в плавающей точке 24 бита считать надо, а не 32. А контроллер
fk0>вообще 8-битный, он 32 бит не за одну, а за 4-8 операций сложит только. С перемножением ещё хуже: там
fk0>32 бита перемножить сильно сложней, чем 24 бита мантиссы. А порядок же тупо складывается при перемножении,
fk0>быстро, одной инструкцией. Зато нормализация при сложении медленей. Но в целом -- обогнало.
fk0>На 32-битном контроллере конечно целочисленные вычисления быстрей, но тоже могут быть нюансы: если есть
fk0>FPU, то вычисления с плавающей точкой могут оказаться быстрей просто потому, что блок FPU работает
fk0>параллельно с целочисленным АЛУ. И компилятор распараллелит инструкции так, что в целом всё быстрей
fk0>посчитается, чем только на одном целочисленном АЛУ.
Всё попахивает непониманием матчасти. Fixed-point это обычные целочисленные вычисления с одним нюансом: при умножении нужно делать сдвиг. В моём случае у AVR есть инструкция, которая делает умножение и сдвиг за то же время, что и обычное умножение. Так что ни при каких условиях (кроме ASIC и/или наличия супер-скалярной архитектуры) не может fixed-point быть медленнее floating-point.