Обновить
23
0
Максим Байтель@StarPilgrim

Разработчик на C++ и других языках

Отправить сообщение

Недистрибутивность деления, или Как я считал среднюю величину

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели3.7K


Казалось бы: сложно отыскать формулу проще, чем нахождение среднего арифметического. Однако код — не формула, вдобавок, если вы пишете на С++, то разного (и в основном неприятного) рода сюрпризы могут ожидать вас где угодно.

Постановка задачи: реализовать функцию uint32_t average(uint32_t a, uint32_t b), не используя типов шире, чем uint32_t, и затем обобщить этот подход на произвольное количество аргументов.
Посмотреть, что из этого вышло

В поиске собственных значений (матриц)

Уровень сложностиСредний
Время на прочтение10 мин
Охват и читатели7.4K


Как найти собственные числа и собственные значения матрицы? Методы, излагаемые в курсе линейной алгебры, основанные на определении — применимы ли они к реальным данным? Существует ли простой алгоритм поиска этих величин, который можно понять, а не просто поверить?
Об этом мы поговорим под катом

I can do it — или как учить английский

Уровень сложностиПростой
Время на прочтение9 мин
Охват и читатели7.4K

Как выучить английский язык? Задавались ли вы этим вопросом? Учили ли вы его в школе и институте, что б потом осознать, что дальше фразы «My namy is...» ваших знаний не хватает, не смотря на потраченное время и усилия?

Если ответ на часть из этих вопросов — да, то добро пожаловать под кат :)

Чтобы сразу расставить все точки над i:

Узнать, что там дальше

Поделить нельзя — умножить или алгоритм быстрого деления по методу Ньютона-Рафсона

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели9.4K


Все мы в школе проходили деление «столбиком» — простой алгоритм, который несложно реализовать, вот только не очень быстрый. В прошлый раз мы рассматривали, как компилятор оптимизирует деление в случаях, когда делитель известен во время компиляции, но применение его напрямую, чтоб оптимизировать деление для делителей, определямых в run-time, невозможно: вычисление констант сдвига и умножения само по себе требует деления.

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

Как поделить не деля или оптимизация деления компиляторам(и)

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели7.1K

Если вы никогда не пробовали смотреть как код на C++ разворачивается компилятором в код Assembly – вас ждёт много сюрпризов, причём, не нужно смотреть какой-то замудренный исходный код полный templates или других сложных конструкций: рассмотрите следущий snippet:

Смотреть код

Имплементация чисел с фиксированной точкой (часть 2)

Уровень сложностиСредний
Время на прочтение11 мин
Охват и читатели1.6K

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

Читать далее

Игрушечная имплементация чисел с фиксированной точкой в C++

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели1.6K

В C++ нет базового типа чисел с фиксированной точкой, в стандартной библиотеке также нет классов для них. В тоже время работа с числами с плавающей точкой (double, float) часто может быть неочевидна (например, ответьте на вопрос: ассоциативна ли операция сложения над ними?), вдобавок язык предоставляет (часто критикуемую) возможность перегрузки арифмитических операторов, подталкивая нас к созданию собственного типа данных.

Прежде чем писать код, давайте повторим мат. часть, а именно о представление чисел в типах uint8_t, int8_t и особенностях арифмитических операциях над ними. Итак, сложенение двух uint8_t происходит по модулю 256, то есть 1+2 = 3, но 1 + 255 = 0, для int8_t отрицательные значения можно ввести следущим образом: отрицательные числа соответсвуют тем безнаковым числам из uint8_t которые складываясь по модулю 256 дадут ноль, то есть -1 будем в памяти выглядить как 255 (FF). Границы типа int8_t -128...+127, для отрицательных чисел старший бит всегда равен 1. При умножении двух int8_t получаем результат типа int16_t, частное от деления int16_t на uint8_t будет иметь тип uint8_t. Все эти сведения носят аболютно тривиальный характер, но, они необходимы для дальнейшего понимания статьи.

Итак, перейдём к основной идее: что если мы мысленно возьмем значение типа int8_t и скажем, что теперь это не число единиц, а скажем, число 1/4 (проговорим словами: это число показывает сколько четвертых частей в исходном числе)? После чего инкапсулируем эту перменную в поле класса и перегрузим для него основные арифмитичекие операторы и напишем свой operator string() для правильного вывода таких чисел. Ниже, можно посмотреть, что получается из этой идеи.

Смотреть код

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность

Специализация

Десктоп разработчик, Бэкенд разработчик