Нужна ли программистам математика? Странный вопрос, учитывая, что на самом деле программисты и занимаются математикой в любом случае — даже если предпочитают не замечать этого.

Меня зовут Пётр — я разработчик и автор курса «Java-разработчик» в Яндекс Практикуме. В этом материале я покажу примеры будничного кода программиста, в которых порой математики не меньше, чем разработки, — и вопрос из заголовка отпадёт сам собой.

Работа с циклами

Какие задачи: задачи, связанные с циклами, проходами по спискам, итеративными вычислениями и кванторами.

Кто решает: все программисты.

Больше всего мы (программисты) любим совершать проходы и обходы, этому нас учат с первых дней.

Самый простой пример:

# Создаём список
список = ['яблоко', 'банан', 'вишня']

# Проходим по элементам списка
for фрукт in список:
    print(фрукт)

И пример посложнее:

// Умножение матриц
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        for (int k = 0; k < 3; k++) {
            result[i][j] += matrix1[i][k] * matrix2[k][j];
        }
    }
}

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

Работу компьютеров и программ мы представляем в виде бесконечных циклов с различными ветвями внутри. Так мы описываем правила обработки для разных элементов виртуального бесконечного списка (потока) событий.

В общем, мы любим последовательности, циклы и ветвления.

Относительные вычисления

Какие задачи: поиск подстроки в строке, работа с индексами, арифметические задачи.

Кто решает: бэкенд-разработчики.

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

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

Ещё программисты любят тексты в различных формах: в виде исходных кодов, которые надо распарсить, в виде команд консоли, которые можно комбинировать. А тексты это последовательности символов с порядковым номером.

Поэтому пример:

def naive_search(text, pattern):
    n = len(text)
    m = len(pattern)
    results = []

    for i in range(n - m + 1):
        match = True
        for j in range(m):
            if text[i + j] != pattern[j]:
                match = False
                break
        if match:
            results.append(i)

    return results

# Пример использования
text = "abracadabra"
pattern = "abra"
print("Подстрока найдена в индексах:", naive_search(text, pattern))

Это пример программы для поиска подстроки в строке. В чём-то наивный, но даже в нём видно, как хитро мы можем играть с индексами, чтобы не выполнять лишних действий.

Если мы будем думать об индексах дальше, мы увидим, как через них просвечивает математика отрезков, открытых и закрытых диапазонов. А ещё в массиве индексов можно построить свои индексы, так в наших руках появляется инструментарий ссылок и арифметики с ними.

Работа с алгоритмами

Какие задачи: сортировка пузырьком, асимптотические оценки, работа с «О» большим и «о» малым.

Кто решает: алгоритмисты.

Есть у программистов и своя ахиллесова пята, это время исполнения команд машиной. Мы пишем алгоритмы, исходные коды которых всё меньше связаны с реальным железом. Это называется языками высокого уровня. Это удобно, но мы теряем ощущение того, как долго выполняются те или иные операции.

Например, мы пишем простой код по наитию, просто переводя словесные рассуждения в алгоритм сортировки.

def bubble_sort(arr):
    n = len(arr)
    # Проходим по всем элементам массива
    for i in range(n):
        # Последние i элементов уже отсортированы
        for j in range(0, n - i - 1):
            # Сравниваем каждый элемент с соседним
            if arr[j] > arr[j + 1]:
                # Если он больше, то меняем их местами
                arr[j], arr[j + 1] = arr[j + 1], arr[j]

# Пример использования
array = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(array)
print("Отсортированный массив:", array)

Узнали? Согласны? А вот компьютер не согласен, и данный алгоритм оказывается не слишком оптимальным с вычислительной точки зрения. Оказывается, что мы наговорили лишнего, а компьютер, повторяя по нашим указаниям этот алгоритм, будет тратить на массив размера N примерно N^2 операций. Для разного количества элементов число операций, конечно, будет разным, но верхний предел количества операций будет N^2.

Поэтому программистам надо уметь видеть усложнения в алгоритмах, неоправданные увеличения количества операций из-за наивных решений, которые легко придумать. Немного подумав над своими словами, можно превратить алгоритм сортировки пузырьком в алгоритм quicksort, а он показывает совсем другой уровень эффективности (N*log(N) вместо N^2).

Работа с графикой

Какие задачи: вычисление абсолютных и относительных координат, длины и ширины, границ и пересечений, масштабирование и работа с пропорциями.

Кто решает: фронтенд- и мобильные разработчики.

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

Поэтому программистам приходится работать с 2D- и 3D-графикой. В этой работе есть свои особенности. Графика в компьютерах изначально растровая. То есть создаётся из единичных точек, но уже в двумерном массиве из строк и колонок.

И конечно, мы любим по этим массивам итерировать. Но это не так просто, как может показаться. Например, начало координат находится сверху слева, а вертикальная ось Y направлена вниз, а не вверх. Поэтому рисовать ель или снеговика приходится в сторону уменьшения координаты.

Кстати, о снеговике. Из пикселей довольно трудно составить идеальный круг. Приходится рисовать подобие круга и полагаться на специальные правила расстановки пикселей. Да и наклонную прямую для ели нарисовать непросто. Хорошо, что для этого есть библиотеки.

Ёлка и снег на Canvas
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ёлка и снег на Canvas</title>
    <style>
        canvas {
            display: block;
            margin: 0 auto;
            background-color: #000;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="400" height="400"></canvas>
    <script>
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');

        const snowflakes = [];
        const numberOfSnowflakes = 100;

        // Функция для создания снежинок
        function createSnowflakes() {
            for (let i = 0; i < numberOfSnowflakes; i++) {
                snowflakes.push({
                    x: Math.random() * canvas.width,
                    y: Math.random() * canvas.height,
                    radius: Math.random() * 3 + 1,
                    speed: Math.random() * 1 + 0.5
                });
            }
        }

        // Анимация снежинок
        function updateSnowflakes() {
            for (let flake of snowflakes) {
                flake.y += flake.speed;
                if (flake.y > canvas.height) {
                    flake.y = 0;
                    flake.x = Math.random() * canvas.width;
                }
            }
        }

        // Отрисовка снежинок
        function drawSnowflakes() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = 'white';
            for (let flake of snowflakes) {
                ctx.beginPath();
                ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI * 2);
                ctx.fill();
            }
        }

        // Функция для рисования ёлки
        function drawTree() {
            ctx.fillStyle = 'green';
            ctx.beginPath();
            ctx.moveTo(200, 300);
            ctx.lineTo(150, 400);
            ctx.lineTo(250, 400);
            ctx.closePath();
            ctx.fill();

            ctx.beginPath();
            ctx.moveTo(200, 250);
            ctx.lineTo(130, 350);
            ctx.lineTo(270, 350);
            ctx.closePath();
            ctx.fill();

            ctx.beginPath();
            ctx.moveTo(200, 200);
            ctx.lineTo(110, 300);
            ctx.lineTo(290, 300);
            ctx.closePath();
            ctx.fill();

            // Ствол ёлки
            ctx.fillStyle = 'brown';
            ctx.fillRect(185, 400, 30, 40);
        }

        // Главная функция анимации
        function animate() {
            updateSnowflakes();
            drawSnowflakes();
            drawTree();
            requestAnimationFrame(animate);
        }

        // Начинаем анимацию
        createSnowflakes();
        animate();
    </script>
</body>
</html>

А ещё нам нужно нарисовать снег. Снег просто так не нарисуешь, ведь снежинка не может быть меньше одного пикселя. А с пикселем есть интуитивная особенность, он представляется лишь точкой с двумя координатами, но на самом деле это прямоугольник. И если два пикселя снежинок нарисовать рядом, получится не снежинка, а кирпич.

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

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

Осознав все эти сложности, программисты придумали векторную 2D- и 3D-графику, в которой нет никаких пикселей, круг действительно является кругом, а изменять масштабы можно в любую сторону и сколько угодно раз.

import numpy as np

def scale_with_aspect_ratio_using_matrix(width_original, height_original, width_target, height_target):
    # Вычисляем коэффициенты масштабирования для ширины и высоты
    scale_width = width_target / width_original
    scale_height = height_target / height_original

    # Выбираем наименьший коэффициент для сохранения соотношения сторон
    scale = min(scale_width, scale_height)

    # Определяем матрицу масштабирования
    scale_matrix = np.array([
        [scale, 0, 0],
        [0, scale, 0],
        [0, 0, 1]
    ])

    # Определяем вектор оригинальных размеров (гомогенная координата)
    original_vector = np.array([width_original, height_original, 1])

    # Применяем матрицу масштабирования
    new_vector = scale_matrix @ original_vector

    # Извлекаем новые размеры из результата
    new_width, new_height = int(new_vector[0]), int(new_vector[1])

    return new_width, new_height

def scale_with_aspect_ratio(width_original, height_original, width_target, height_target):
    # Вычисляем коэффициенты масштабирования для ширины и высоты
    scale_width = width_target / width_original
    scale_height = height_target / height_original

    # Выбираем наименьший коэффициент для сохранения соотношения сторон
    scale = min(scale_width, scale_height)

    # Вычисляем новые размеры
    new_width = int(width_original * scale)
    new_height = int(height_original * scale)

    return new_width, new_height

# Пример использования
original_width = 1920
original_height = 1080
target_width = 800
target_height = 600

new_width, new_height = scale_with_aspect_ratio(original_width, original_height, target_width, target_height)
print(f"Новые размеры: {new_width}x{new_height}")

new_width, new_height = scale_with_aspect_ratio_using_matrix(original_width, original_height, target_width, target_height)
print(f"Новые размеры: {new_width}x{new_height}")

Программистам остаётся только правильно высчитывать коэффициенты и соотношения сторон, а также разобраться наконец с понятием матриц преобразования координат. Без этого красивую игру не построить и приятный эффект перехода в мобильном приложении не реализовать.

Непосредственно математика

Какие задачи: задачи, связанные с прикладной математикой, статистикой, интерполяциями.

Кто решает: все программисты.

Конечно, в работе программиста встречаются и математические задачи. Любой язык программирования предполагает, что в нём будут производиться арифметические вычисления. Зачастую бóльшая часть математических функций реализована в библиотеках. Какую именно формулу мы будем описывать на языке программирования, зависит от задачи, но, как и в случае с алгоритмами, приходится помнить, что код исполняет реальный компьютер, со своими ограничениями и пределами. Например, с предельным размером целочисленных значений.

Пока наши целочисленные вычисления ограничиваются индексами в массивах (и не связаны с big data), мы можем не думать о природе целых чисел. Но когда дело доходит до вычислений, мы очень быстро можем наткнуться на неожиданный результат.

public class FactorialOverflow {
    public static void main(String[] args) {
        int number = 13;
        int factorial = 1;

        for (int i = 1; i <= number; i++) {
            factorial *= i;
            System.out.println("i = " + i + ", factorial = " + factorial);
        }

        // Обратите внимание на результат, который не является корректным значением 13!
        System.out.println("Факториал " + number + " равен " + factorial);
    }
}

Вычисляем быстрорастущую функцию факториала — и нам хватает 13 итераций, чтобы наткнуться на лимит 32-битного числа. Неприятно будет пропустить такую ошибку в продакшн. Кажется, какой-то производитель рентгеновского оборудования столкнулся с таким багом, и последствия для пациентов были печальными.

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

int color = 0xAABBCCDD; // Пример: A=AA, R=BB, G=CC, B=DD

int alpha = (color >> 24) & 0xFF;
int red = (color >> 16) & 0xFF;
int green = (color >> 8) & 0xFF;
int blue = color & 0xFF;

Например, здесь мы извлекаем компоненты цвета размером 1 байт (8 бит) из целого числа длиной 32 бит.

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

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

public class EpsilonFinder {
    public static void main(String[] args) {
        double epsilon = 1.0;

        // Пока добавление эпсилон к 1.0 дает 1.0, уменьшайте эпсилон
        while (1.0 + epsilon != 1.0) {
            epsilon /= 2.0;
        }

        // Выйдя из цикла, эпсилон будет в два раза меньше необходимого, поэтому умножаем на 2
        epsilon *= 2.0;

        System.out.println("Число эпсилон: " + epsilon);
    }
}

Поэтому код выше кажется невыполнимым, но в реальности компьютер на каком-то масштабе величин просто перестаёт их видеть.

Работа с множествами

Какие задачи: задачи, связанные с выборками, пересечениями множеств, SQL-выборками, ООП и классами.

Кто решает: все программисты.

Впрочем, задачи, которые мы решаем, не всегда напрямую связаны с расчётами, формулами и числами. Например, задачи на описание или моделирование предметной области в виде сущностей и их связей.

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

Речь, конечно, про ООП, про понятие классов, множеств, перечислений. Мы описываем множества сущностей через их свойства и поведение. С помощью наследования классов мы расширяем поведение через заужение множеств, меняем поведение сущностей. С помощью ООП мы превратили компьютер из большого калькулятора в универсальную машину вычислений для любой из вещей, что есть в этом мире.

Конечно, в некоторых случаях строгая логика ООП-подхода приводит к забавным парадоксам, как, например, пример ниже:

class Rectangle {
    protected int width;
    protected int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getArea() {
        return width * height;
    }
}

class Square extends Rectangle {
    public Square(int side) {
        super(side, side);
    }

    @Override
    public void setWidth(int width) {
        this.width = width;
        this.height = width; // Неправильная логика, специфичная для квадрата
    }

    @Override
    public void setHeight(int height) {
        this.height = height;
        this.width = height; // Неправильная логика, специфичная для квадрата
    }
}

Тут мы наблюдаем ошибочную наивную классификацию квадрата как прямоугольника (что с точки зрения математика, возможно, даже верно). Говоря про ООП, нельзя не затронуть и параллельную вселенную описания сущностей — реляционные базы данных и их подход к классификации, атрибутированию предметной области.

SELECT c.*
FROM creatures c
JOIN habr_readers hr ON c.id = hr.creature_id
WHERE c.type = 'человек'
  AND c.location = 'Европа'
  AND c.is_alive = true;

Языковые средства ООП или SQL понятны любому человеку и в то же время концентрируют в себе большое количество точных (или не очень) логических высказываний о мире вокруг нас.

Функциональное программирование

Какие задачи: работа с MapReduce, фильтрами, лямбдами, свёртками.

Кто решает: все программисты.

Мы начали эту статью с циклов, потому что все когда-то начинали с циклов. Но параллельно с циклами существует целый мир рекурсивных и родственных с ними функциональных вычислений.

Теория говорит нам, что любые вычисления полноценны и равнозначны — и циклы, и рекурсия, и функциональный подход, — и всё же в статьях по теме часто можно встретить эпитеты «элегантные» и «математичные», применяемые к рекурсивным алгоритмам или функциональным декларативным описаниям программ.

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

def group_by_country(entities):
    def helper(entities, index, grouped):
        if index >= len(entities):
            return grouped

        entity = entities[index]
        country = entity['страна']

        if country not in grouped:
            grouped[country] = []

        grouped[country].append(entity['имя'])

        return helper(entities, index + 1, grouped)

    return helper(entities, 0, {})

# Пример использования
creatures = [
    {'имя': 'Лев', 'страна': 'Африка'},
    {'имя': 'Панда', 'страна': 'Китай'},
    {'имя': 'Коала', 'страна': 'Австралия'},
    {'имя': 'Слон', 'страна': 'Африка'},
    {'имя': 'Тигр', 'страна': 'Индия'},
]

result = group_by_country(creatures)
print(result)

Наглядность, описательность кода развивается в функциональном программировании. В каком-то смысле мы описываем уже не действия компьютера, а образ итогового результата вычислений. Например, так выглядит алгоритм группировки читателей Хабра по стране обитания на языке Haskell. Элегантно, ничего не скажешь.

groupHabrReadersByLocation =
    map (\\group -> (location (head group), group)) .
    groupBy ((==) `on` location) .
    filter (\\c -> readsHabr c && isAlive c && creatureType c == "человек")

Этот стиль описания изолирует нас от циклов, условий и итеративной природы вычислений внутри компьютеров.

Математика+

Какие задачи: задачи, связанные с нейросетями, степенными функциями, экспонентами, логарифмами, нелинейными функциями срабатывания, производными, матрицами, тензорами и вероятностями.

Кто решает: разработчики нейросетей, специалисты по машинному обучению и работе с большими данными.

В конце (по порядку, но не по значимости) стоит упомянуть области IT, в которых, на мой взгляд, алгоритмов и программирования как таковых немного меньше, чем интересной математики.

Это, конечно же, актуальная тема нейросетей, в разработке которых, в сущности, все задачи программирования и пересчёта тензоров уже решены и оптимизированы. А вот математика, которая кроется за готовыми функциями самых популярных фреймворков, вызывает у меня неподдельный интерес — а точнее вызывает интерес то, как понимать комбинации разных слоёв и различных функций активации.

import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.utils import to_categorical

# Загрузка данных MNIST
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# Нормализация данных
x_train = x_train / 255.0
x_test = x_test / 255.0

# Преобразование меток в категориальный формат
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)

# Создание модели с несколькими слоями
model = Sequential([
    Flatten(input_shape=(28, 28)),  # Преобразование 28x28 изображений в 784-длинные векторы
    Dense(128, activation='relu'),  # Первый скрытый слой с 128 нейронами
    Dense(64, activation='relu'),   # Второй скрытый слой с 64 нейронами
    Dense(10, activation='softmax') # Выходной слой с 10 нейронами
])

# Компиляция модели
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# Обучение модели
model.fit(x_train, y_train, epochs=5, batch_size=32, validation_split=0.2)

# Оценка модели
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'Точность на тестовых данных: {test_acc:.4f}')

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

Выводы

Что можно сказать в итоге? Что математика программисту точно нужна. Но вот степень погружения и конкретные области этой науки — зависят от сферы работы и решаемых задач. Это значит, что начать свой путь и даже успешно заниматься программированием можно и без специального образования или глубоких знаний в математике. Но если они есть, это будет плюсом: расширит выбор возможных направлений и сократит время на обучение в будущем.

Комментарии (50)


  1. T968
    15.01.2025 06:47

    Если перефразировать, то вопрос гораздо понятней.

    Зачем каменщику сопромат?

    Или численные методы решения уравнений в частных производных.


    1. lomo_leaf
      15.01.2025 06:47

      Почему сразу каменщик?


      1. Vladimir_III
        15.01.2025 06:47

        Почему нет?


        1. lomo_leaf
          15.01.2025 06:47

          Это обесценивание, сравнение с профессиями, для которых требуется начальный уровень образования.


          1. Zenitchik
            15.01.2025 06:47

            Вы просто мало знаете о каменщиках.


  1. LaptevVV
    15.01.2025 06:47

    Линейное векторное пространство над полем Галуа - каждый программист в мире каждый день пользуется 100500 миллионов раз.
    Если математику знаешь и ориентируешься, то ты инженер-разработчик высокого класса.
    Если не знаешь и не ориентируешься - ты кодер-техник, не более...


    1. DeadFox61
      15.01.2025 06:47

      Ох что же я буду делать без титула такого классного


      1. LaptevVV
        15.01.2025 06:47

        Да титул здесь не при чем.
        А возможности устроиться на разнообразные работы и на разные уровни должности - с пониманием математики и без...


        1. DeadFox61
          15.01.2025 06:47

          Лучше научиться читать реп, тоже возможностей открывает. Если клёво реп не читаешь, то ты лох без сучек и братвы, не более... А если знаешь и можешь выдать крутой флоу, то ты классный чел, респектовый эмси высокого класса


          1. LaptevVV
            15.01.2025 06:47

            Тогда что вы делаете на программерском ресурсе ?
            Идите учите реп...:)))))


            1. DeadFox61
              15.01.2025 06:47

              Так я программист, просто лоховской, кодер техник, не более. Игровой движок не пишу, графы для приложения доставки не обхожу и вообще я так, бекенд программист обычный, не высокого класса кароч


          1. Zenitchik
            15.01.2025 06:47

            Рынок читателей репа слишком мал, чтобы реально рассчитывать что-то на этом заработать.


            1. DeadFox61
              15.01.2025 06:47

              Я думаю он даже выше чем рынок программистов где нужна какая-то хоть сколько то сложная математике


        1. IUIUIUIUIUIUIUI
          15.01.2025 06:47

          А возможности устроиться на разнообразные работы и на разные уровни должности - с пониманием математики и без...

          Около нуля разницы.

          Есть основания считать, что я математику понимаю (диплом прикладного математика от первого вуза страны, примерно 8 лет ковыряний чистой математики после выпуска «для себя»), и на работе она используется примерно никак.

          Более того, чем больше на работе серьёзной глубокой математики, тем меньше за неё платят. Обмазываться матлогом и пруверами для формальной верификации (и разработки методов формальной верификации в команде с PhD-чуваками из топовых универов мира) — сто тугриков в час, ваять фронтенды на реакте с двумя годами опыта за плечами и отсутствием формальной вышки — 200, быстро перекладывать байтики на C++ — 500.


  1. ChePeter
    15.01.2025 06:47

    "Если математику знаешь и ориентируешься" но пишешь при этом код сам,то всё равно кодер-техник.


    1. LaptevVV
      15.01.2025 06:47

      1. До написания кода надо сначала понять, что именно писать... :)))

      2. В наиболее модных направлениях (ИТ + DS) без математики вообще делать нечего.


      1. IUIUIUIUIUIUIUI
        15.01.2025 06:47

        Необходимость математики в DS несколько преувеличена. Для import sklearn не нужно понимать доказательство и вывод PCA, например.


    1. Zenitchik
      15.01.2025 06:47

      А что, надо через "испорченный телефон" объяснять кодеру-технику, что он должен написать? Так себе идея.

      Написать код самому - быстрее, и менее чревато ошибками.


  1. toxa82
    15.01.2025 06:47

    За 15 лет вэб программирования обычно максимальное знание математики что требуется это посчитать какие-то проценты (например НДС). Но иногда попадаются интересные проекты в виде технических калькуляторов цены, и там для отрисовки графиков приходится вспоминать элементарную алгебру и геометрию, например найти корни квадратного уравнения, найти точку пересечения графиков, или длину кривой линии. Ну конечно если залезть в нейронные сети, то там уже придется вспоминать высшую математику, производные и первообразные. Так что думаю требуемая глубина знаний математики зависит от вашей сферы.


    1. LaptevVV
      15.01.2025 06:47

      Естественно. Глубина использования математики зависит от задач.
      Но знание математики раздвигает твои возможности по сферам работы.
      Ты просто более конкурентоспособен становишься.
      Не считая того, что математика "ум в порядок приводит".
      А фронт-ендщики веб-программисты - это такие слесари, а не инженеры разработчики... :))))


      1. toxa82
        15.01.2025 06:47

        Я back-end программист ))) та и вообще все прогеры слесари 95% рабочего времени


        1. k4ir05
          15.01.2025 06:47

          При работе с легаси скорее даже сантехники ;)


      1. lomo_leaf
        15.01.2025 06:47

        Каменщики, слесари, вы низкого мнения о нашем брате-программисте 1-ой категории... У него высшее образование, однако.


        1. Zenitchik
          15.01.2025 06:47

          У бухгалтера тоже высшее образование.

          Это артефакт инфляции понятия "высшее образование".


          1. lomo_leaf
            15.01.2025 06:47

            Инфляция на сколько процентов?


  1. Jijiki
    15.01.2025 06:47

    зависит от того что вы программируете в текстовом редакторе может не нужны интеграллы, диференциалы, векторная/матричная, кватернионы


    1. wataru
      15.01.2025 06:47

      Зато там нужны всякие очень сильно продвинутые структуры данных. Для понимания которых нужно знать комбинаторику и дискретную математику.


  1. voidinvader
    15.01.2025 06:47

    Программисту больше нужна дискретная математика и логика, а не вышмат в классическом понимании. За десять лет разработки, так ни разу и не было случая, куда можно было бы производную приладить.


    1. LaptevVV
      15.01.2025 06:47

      Алгебра тож нужна. Многочлены, векторы, матрицы...
      Линейное векторное пространство над полем Галуа - это оно. :))))
      Шифрование и кодирование с защитой от ошибок - самое то.
      Аналитическая геометрия - чтобы графику понимать...
      Теория графов, теория вероятностей и статистика
      Методы оптимизации, численные методы
      Это навскидку.


      1. IUIUIUIUIUIUIUI
        15.01.2025 06:47

        Многочлены, векторы, матрицы...

        Аналитическая геометрия - чтобы графику понимать...

        Сколько людей, работающих даже, скажем, над 3D-графикой, понимает, почему матрицы надо умножать так, как они умножаются?

        Более того, я не уверен, что средний выпускник Физтеха это понимает, потому что Беклемишев в своём замечательном (нет) курсе линала это просто постулирует.

        Линейное векторное пространство над полем Галуа - это оно. :))))
        Шифрование и кодирование с защитой от ошибок - самое то.

        Я занимался блокчейном, и мне даже там это не пригождалось. Мне это вообще нигде не пригождалось.

        Методы оптимизации, численные методы

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

        Теория графов, теория вероятностей и статистика

        Достаточно почти-школьного уровня (см. выше — я занимался машинным обучением). Способный поступить в вуз человек способен это освоить на достаточном для практических задач уровне и после.

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


        1. LaptevVV
          15.01.2025 06:47

          Берешь библиотеку - ключевое.
          Если знаешь соответствующую математику - ПИШЕШЬ библиотеку.


          1. IUIUIUIUIUIUIUI
            15.01.2025 06:47

            Зачем её писать, если она вон уже готовая лежит? Чтобы было хуже, менее отлаженно и более тормознуто?


            1. LaptevVV
              15.01.2025 06:47

              Так они и лежит потому, что ее КТО-ТО написал.
              А не ты - ибо математики не знаешь...


              1. IUIUIUIUIUIUIUI
                15.01.2025 06:47

                Я сидел-ждал, когда её кто-то написал? Нет. Она была готовая уже до того, как я пришёл — моё знание математики тут не влияет примерно никак: для подавляющего большинства программистских задач серьёзные математические библиотеки уже написаны, и программисту не приходится писать свою математику.

                Да и с чего ты взял, что я математику-то не знаю? Типа, если бы «знал математику», то бросился бы переизобретать все используемые библиотеки с нуля?

                Интересно, а для обычных, нематематических библиотек это тоже работает? Типа, я использую std::unordered_map потому, что не знаю, как работают хэшмапы (подсказка: знаю, всё равно использую std::unordered_map)? Я использую либу для блумфильтров потому, что не знаю, как работают блумфильтры и почему там такая-то оценка вероятности коллизий (подсказка: знаю, всё равно использую готовые либы вместо написания своих блумфильтров)?


    1. Zenitchik
      15.01.2025 06:47

      Мне случилось писать автодифференциирование, чтобы на криволинейных шкалах (заданных параметрически) штрихи подрисовывать.


  1. JBFW
    15.01.2025 06:47

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

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


    1. Zenitchik
      15.01.2025 06:47

      Их бы в глобальные перенести, выделить раз и надолго - но это не по-феншую, да и непонятно

      Автоматизировать этот процесс надо...


      1. IUIUIUIUIUIUIUI
        15.01.2025 06:47

        Жаль, что проблема останова не даёт.


  1. DuhovichSasha
    15.01.2025 06:47

    Ваш вопрос подрывает рекламу курсов, что любой гуманитарий за неделю станет иг стециалистом на их курсах.


    1. coodi
      15.01.2025 06:47

      Добавят прост неделю математики в курсы


  1. gev
    15.01.2025 06:47

    А где формальная логика, теория типов и прочий полиморфизм?))


    1. coodi
      15.01.2025 06:47

      Математикам этого не надо, видимо


    1. same_one Автор
      15.01.2025 06:47

      Формальную логику постарался упомянуть в связке с ООП и SQL. Акцент в статье был именно на разделах математики, которые хорошо бы знать/понимать.


  1. HADGEHOGs
    15.01.2025 06:47

    Петр, не пиши больше. Не ваше это.


  1. coodi
    15.01.2025 06:47

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


    1. Zenitchik
      15.01.2025 06:47

      А проверить? Хотя бы прикидочный расчёт сделать, и сравнить с выводом библиотеки?


    1. LaptevVV
      15.01.2025 06:47

      А кто написал библиотеки ? Инопланетяне что ли ?
      Людьми, которые математику как раз знают... :))))


  1. assad77
    15.01.2025 06:47

    Проблема программирования в том, что нужно знать много обо всем и лишь с какой-то вероятностью какое то знание пригодится.

    Не каждый день нужна математика. Далеко не каждый. Но иногда это нужно. Нужно и придумать и сделать и обосновать. И в итоге все кто участвует так или иначе в дискуссии должны математику знать.

    Это касается не только математики но и технологий. Но с технологиями легче. Про них можно прочитать и понять. Математика же может иметь уровень вхождения.

    Я лично считаю, что хорошему разработчику нужно хорошо знать математику, чтобы раз в два года сделать хорошее решение, за которое действительно не стыдно.


    1. Zenitchik
      15.01.2025 06:47

      Математика же может иметь уровень вхождения.

      Да не, в неё просто надо вползать постепенно, и на это уходят годы. А резко вдруг - не войдёшь.


  1. RedWolf
    15.01.2025 06:47

    Зачем байты в инт пихать? char (ну или что там ещё, uint8_t или что-то подобное) логичнее, меньше места жрет и & 0xFF не нужен.