вторник, 12 января 2010 г.

[comp.prog.flame] Можно программировать и не зная математики

Вчера, сначала в комментариях к заметке “Краткие впечатления от статьи “Элементы функциональных языков”” начали спорить beroal и Skynin о роли и месте математики в программировании. А затем в RSDN-овской разборке я прочел интересное заявление (автор этого заявления окончил БГУ (Минск), факультет прикладной математики, если я правильно расшифровал ФПМ):

Невозможно знать математику и не научиться программировать.
А то, что муж за нее писал и не знал математику тоже ложь, там же лабы
все с математическими алгоритмами.

Т.е. четко прослеживается мнение о том, что математики не могут не программировать, а не математики программировать не могут. Или, в более простой и категоричной форме – математик может программировать, не математик – не может.

Данный тезис легко опровергается примерами. Взять, например, меня. Имхо, я как раз очень яркий пример того, как не зная математики (практически вообще), можно нормально программировать.

В школе, класса до 9-го, с математикой у меня было все нормально. Но это было до тех пор, пока шли вещи, которые можно было как-то вообразить – корни чисел, прямые и плоскости, повороты и преобразования и пр. Даже с логарифмами еще все было нормально. Но вот когда начались пределы, производные и интегралы, наступило начало конца :)

Для того, чтобы учиться на программиста, мне пришлось поступать на математический(!) факультет. Хорошо еще, что на специальность “Программное обеспечение ВТ и АС”. Но все равно, математики было много, особенно на первых курсах. Тут уже был конкретный приплыздец, полное непонимание того, что мне читают (за исключением, разве что, дискретной математики). Выплывал я только за счет тупого зазубривания каких-то формул (вроде производных и интегралов основных функций). Ну и плюс нас натаскивали на решение однотипных задач, в которых нужно было только запомнить, в каком месте подставить подходящую формулу. Если же попадалась нестандартная задачка – все, суши весла.

Вероятно, здесь было всего поровну – и моей лени+разгильдяйства, и моей тупости, и отсутствия простых и понятных демонстраций смысла математических конструкций. Хотя я больше склоняюсь к другому объяснению – у меня не достаточный для занятия математикой уровень абстрактного мышления + особенности памяти, поскольку я быстро забываю все, чем не пользуюсь. А в математике такое не проходит – стоит забыть, скажем, что такое базис пространства в аналитической геометрии, и после этого уже не поймешь какую-нибудь очередную тему в матанализе.

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

Так что, если у кого-то есть сомнения в том, что программировать можно и не зная математики, то просто посмотрите на меня :)

Другое дело, что я не знаю, программировал бы я настолько хорошо, если бы в школе и в универе меня не тренировали усиленно математическими дисциплинами. Все-таки битиё определяет сознание и такое количество математики, конечно же, привело к какому-то (пере)упорядочиванию моих мозгов. Но в любом случае – учить не означает знать.

Для меня же очевидно (да, это большое и жирное ИМХО), что математика и программирование требует различного склада ума. По большому счету математика – это наука. И ученый не обязан уметь класть кафель. Тогда как программирование (в подавляющем большинстве случаев) – это ремесло, временами на грани с искусством. И от программиста как раз требуется умение “класть кафель”, а вот разлагать функцию в ряд Тейлора – отнюдь. Поскольку программирование сейчас – это очень обширная область деятельности, в которой существуют отдельные направления, сильно завязанные на математике (та же верификация программ). Смею, однако, предположить, что такими задачами занимаются считанные проценты от общего числа программистов.

Тема явно флеймовая и еще много можно было бы сказать, но, как в анекдоте “нутром понимаю, что 0.5 и 0.5 будет литр, а математически выразить не могу” ;)

14 комментариев:

Dmitry Vyukov комментирует...

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

Quaker комментирует...

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

Aleksey Dobrunov комментирует...

Начнем с того, что программирование, как наука, это подраздел математики. Машины Тьюринга вроде как основы информатики.
Высказывание на rsdn, скорее всего идет из следующих соображений . Программирование - раздел математики. Очень близкий к дискретной математике. Дискретная завязана на алгебру, алгебра на мат анализ. В общем каждый раздел черпает многое из другого. Соответственно чтобы понять более высокий раздел нужно изучить нижележащие. Но это как предположение.
Сам я по образованию математик, но специализация системное программирование. (УрГУ мат-мех :-) ). Ну а раз мат-мех, то матан алгебра дифуры и все все все... Я раньше не особо понимал на кой оно мне как программисту. Сейчас я дошел до некоего смысла. Все зависит от того какой ты программист, т.е. твоя специализация. Если ты пишешь бух. программки, то тебе хватит и школьной математики. Ну а если компиляторы то тут уже нужна математика . Книга дракона -). Ведь многие вещи надо доказать, перед тем как написать. Ну там что язык полный или что то типа того (не помню уже). А доказательства строятся на математике.
Да и многие другие вещи, которые ты интуитивно понимая что они верные, должен вначале доказать а потом использовать.
А вообще, чтобы быть программистом, как мне кажется, главное чтобы у тебя был математический склад ума. Вспоминаем матан, доказательства теорем - "для всех i принадлежащих R ... Повторим для всех k из диапазона." Ну а не это ли мы пишем в программах? Так вот изучение математики настраивает голову рассуждать в таких терминах.

eao197 комментирует...

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

У меня со временем сложилось несколько другое мнение. Математический склад ума -- это способность оперировать абстракциями вроде "множества R", "для каждого i", "подмножество элементов m, таких, что..."

Тогда как для программирования более критично уметь отвечать на вопросы "что? зачем? как? почему так?" Может эта способность как-то пересекается со способностями к математике, но не на 100%. Именно поэтому далеко не все математики являются хорошими программистами.

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

Aleksey Dobrunov комментирует...

>Тогда как для программирования более критично уметь отвечать на вопросы "что? зачем? как? почему так?" Может эта способность как-то пересекается со способностями к математике, но не на 100%. Именно поэтому далеко не все математики являются хорошими программистами.

очень сильно пересекается. это же умение доказывать теоремы. "почему так?" - т.к. если тото , то ...
зачем? - если не сделаем то ....

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

Ну и опыт играет очень важную роль. Так пример из учебы. Репин, ио не помню, профессор. Ему уже реально за 70, по виду не понять как он вообще преподает. А на практике по с++, утрет нос любому студенту. Лахтин и Баклановский. Первый преподает pascal, с++ , второй ассемблер. Взглянув на исходник программы всего пару секунд показывает где ошибка, или приводит тест, на котором программа валится.

eao197 комментирует...

Кстати о математическом мышлении: вот хороший пример -- Con Kolivas -- врач-анестезиолог, который в свободное время занимался планировщиком в ядре Linux.

eao197 комментирует...

>это же умение доказывать теоремы. "почему так?" - т.к. если тото , то ...
зачем? - если не сделаем то ....


Не знаю, теорем не доказывал никогда. Только учил уже готовые доказательства.

Я всего пару раз наблюдал работу математиков. В первом случае выполнялся подбор какого-то хитрого ядра несобственного интеграла для расчета трения и износа. Это было вообще чистой воды экспериментательство -- попробовали один вариант, програли через MathLab какие-то расчеты, не понравилось. Попробовали второй вариант -- не понравилось. Почитали какие-то книжки, попробовали еще что-то.

Во втором случае это был вывод каких-то хитрых уравнений. Там шло какое-то преобразование одних выражений к другим.

Как по мне, так это было слишком далеко от того программирования, которым я занимался.

Skynin комментирует...

Программирование - раздел математики.
Это-то как раз и не так :)

Когда-то, наверное до Алгола, было верно, оттуда и осталось это эхо.

Для меня это утверждение звучит как:
Умение говорить на языке - раздел лингвистики.
Бегать рекордно стометровку - раздел медицины.
Вождение автомобиля - раздел автомобилестроения.
а само автомобилестроение - раздел математики.

"для всех i принадлежащих R ... Повторим для всех k из диапазона." Ну а не это ли мы пишем в программах?
Я пишу - "для каждого элемента коллекции для которого выполняется условие истинности выполняю действие такое-то". Никаких "принадлежащих", "из диапазона" и тем более i, R, k. То есть при программировании у меня никаких математических терминов в уме не возникает. А так как учил и матан, и прикладную (КПИ, ФИВТ), и со второго курса программировал, то разницу что у меня в уме происходит, и что использую - могу оценить.
Можно программировать мысля математически. А можно - и не мысля. Если второго не бывает - то тогда да, раздел математики. А если можно обойтись - то не раздел.

А если нужен мудреный алгоритм - то открываешь Вирта - и копипастишь :) По крайней мере я читал в его книгах только общие рассуждения и код. А доказательства, расчеты эффективности пропускал - "поверил на слово". Потому что уже знал как пользоваться профайлером, и что оценка эффективности по времени должна быть привязана к типическому использованию модуля, или программы.
Затасканный пример - какая разница пузырьком сортировать или квиком - если 1 запрос к БД выполняется на порядки дольше?

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

Ну а если компиляторы то тут уже нужна математика
А если штатный программист какой-нить фармасьютикал, в отделе моделирования препаратов - то органическую химию желательно знать. Значит - программирование - раздел химии?

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

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

Но конечно - как всякий инженер - программист обязан изучать математику в студенчестве, и знать азы, чтобы относительно легко находить ответы в книгах и справочниках. В сложных же случаях - обращаться к математику, как специалисту, а не заниматься "самолечением" :)

Quaker комментирует...

А если нужен мудреный алгоритм - то открываешь Вирта - и копипастишь :) По крайней мере я читал в его книгах только общие рассуждения и код. А доказательства, расчеты эффективности пропускал - "поверил на слово".
Недавно появилась обновленное издание Вирта "Алгоритмы и структуры данных" (http://www.ozon.ru/context/detail/id/4803785/). Там написано все очень хорошо (с предусловиями и постусловиями), каждая строчка продумана и выверена. Кстати, по проведению доказательств корректности операторов можно почитать брошюрку Бейбера "Программное обеспечение без ошибок" (http://ermakov.metasystems.ru/download/Beiber-SoftWithoutErrors.pdf). Понятно, что каждую строчку таким образом доказывать не будешь (трудоемко), но знать не помешает.

CrystaX комментирует...

Столько споров - и все ни о чем... Просто математика (по определению Дейкстры) - это искусство и наука эффективных рассуждений. А "множества R", "для каждого i", "подмножество элементов m, таких, что..." - это частности. Отчего такая узость взглядов?

eao197 комментирует...

2Quaker: за ссылочки спасибо, почитаем.

Rustam комментирует...

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

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

Aleksey Dobrunov комментирует...

хорошо. в некоторых вещях я не прав. полез доказывать не то утверждение.
все таки если отталкиваться от "математик может программировать, не математик – не может", то да , оно не верно. Есть люди которые и без математики программируют.
Но как я писал выше , все таки нужно или не нужно знать математику программисту зависит от его направленности.

eao197 комментирует...

>Но как я писал выше , все таки нужно или не нужно знать математику программисту зависит от его направленности.

Мне кажется, что "знать математику" -- это еще более размытый термин, чем "уметь программировать". Сейчас Web-программист не может просто взять и начать писать драйвера. Точно так же, как алгебраист не сможет просто так заниматься дифурами.