僕自身は大したエンジニアではないのですが、一応エンジニアとして働いてお金をもらっているし、東工大生なので数学やCSについては学部レベルですが少しは学んでいるというような状態です。プログラミングに数学やCSってどの程度役に立っているのか自分の肌感程度ですがまとめました。
これからエンジニアを目指す方向けに書いていますが、「一人の意見」くらいに受け取って鵜呑みにしないでもらえると嬉しいです。
「仕様」を「コード」に変換するのに数学は使わない
プログラミングに数学とCSはいらないというのは正しい側面も持っているような気がします。というのも、プログラミングが「仕様」を「コード」に変換することだとしたら、数学もCSも使わないはずだからです。基本的にはライブラリの仕様とforとifくらいわかっていればコードはかけます。ここに学問的な思想は登場しません。研究室で書くコードのレベルでも実装フェーズになるとやるだけな気がします。
では、どのようなタイミングで、数学やCSを使うのか。
それは、「要件」を「仕様」に変換するタイミングだと思います。
しかし、個人開発のWebアプリケーションの開発をするくらいであれば、「要件」を「仕様」に変換するタイミングでも数学やコンピュータサイエンスについて全く勉強するつもりのない人でもこなすことができます。
つまり、エンジニアとして働く上で、数学にしろCSにしろ決して「MUST」ではないという認識を持っていいと思います。(機械学習エンジニアなどの職種ではMUSTです。)
エンジニアが数学やCSを勉強する意味はない?
それは全くの間違いです。数学もCSも「できたほうがいい」です。
なぜなら、ものの仕組みがわかるようになってくると「簡潔にできるようになる」からです。コードの書き方はわかったけど、完全にはわかってないという人は、必ずなにかしらの形(サンプルコード)に乗っかる必要があります。めんどくさかろうが、期待する動作を得られなかろうがなんだろうがとりあえず、それをコピペすることしかできません。あとから問題のある部分をゴリゴリと別のジョブを立てたりして解決するしかなくなるんです。それが内側で何をやっているのかがわかってくると、より簡潔にやることができるようになるわけです。
そして、物事や現象の根底にあるものというのは、要件がどれだけ複雑になったとしても変わりません。
0→1開発の簡単な要件ならメソッドでパッとかけるで問題ないかもしれません。でも本当に重要で複雑な仕組みを作る際には、ライブラリのメソッドで終わりとかじゃないんです。
自分の書いたプログラムがどのように動作するのかを自分の言葉できちんと説明できるようになる必要があります。
じゃあ、そのライブラリの実装ではうまくいかなかったらどうするんですか?概念としてやりたいことや仕様がわかっていれば、自分で書くこともできます。何が問題で、何を解決する必要があるのかについて議論することもできます。そういうことができるようになる力を身につけなければいけないんです。勉強ってそういうものなんです。そのためには「数学」も「CS」も必要になる場合があります。
プログラミングに数学をなぜ使うの?
一言で表すなら、「便利」だからです。別に言葉を使って頑張って説明してもいいけど、数式の方がわかりやすくて厳密だよねって感覚で使います。実際に、システムでも計算量とか情報量とかエントロピーとか様々なものを数式を使って定義しています。
なんでそんなに数式がわかりやすいかというと、この変数を増やしたらこの変数は減るなとか、出てきた数式を眺めると現象が活き活きと現れてくるからです。
数学をやっていると、普段無意識に言葉を話すようにスッと式を書くようになるし、スッと式が表す現象が読み取れるようになります。そして、極めて厳密です。だから、めちゃくちゃ便利なんです。
数学が苦手な方は、数式を計算式だと思っているような気がします。だから、読み取れないから言葉で説明してくれというような状態になってしまいます。
東工大のメンバーで議論するときは真逆になります。「言葉ではわからないから式を書いてくれ式を」ってよく言われます。つまり、数式自体が言葉なんです。だから、当然情報科学の分野でも数学は登場します。数学は極めて洗練された美しい言葉だから使われるのです。
理想と現実
ここで、現象をきっちりと語っていくことができるようになることを目標に勉強する必要があるという前提に立つわけです。
しかし、そうすると数学上の知識だったりちゃんとした証明が必要になったりするわけです。
その時に、「まず使ってみる」ということが大事になります。
「全部完璧に証明したり、全部完璧に現象を理解したりしなければ何一つ使えません」なんて言ってたら、何一つ作れないで終わってしまいます。何かをプログラムで実現するときは常にそうです。
少し思い出して欲しいのですが、高校2年生では、微分と積分の定義について習いますね。この時に「数はいくら細かく分けていってもその間にまだ要素はあるのか?」なんて考えている受験生はほとんどいないと思います。こういうのは、ほとんどの受験生が「事実を事実として受け入れる」という手段をとっているわけです。ところが大学に入学後はこう言ったことが受け入れるわけにはいかなくなってきます。このような順序で問題ありません。
つまり、今持っている知識をベースにして、理屈を展開していき、「ここはわからないな」という部分は念頭に置いて「受け入れる」ということをします。色々動かしてみて馴染むことから入り、他の知識が追いついて準備が整った、あるいは必要性に迫られたという段階でより詳しくみていけばいいということです。
微分積分や極限の概念を理解した後だからこそ、「有理数コーシー列」だの「有理数の稠密生」だの新しい概念に出会っても対応できるのではないかなと思います。
私には才能がないなんて言わないで
とはいえ、「数学とCSについてすごく詳しくないと物の仕組みがわかるようにならないか」というとそれも必ずしもそうとは限らないと思います。Webやスマホの機能開発なら知ってると有利くらいでしかないと思います。
大事なのは、「どうせ実験してもわからないでしょう」とか「私には才能がないから」とか思わないことです。
そして、「現象を実態を伴って理解しようとする」というスタンスを持ち続けることが大事だと思います。
数学やコンピュータサイエンスの知識不足にコンプレックスを感じて、本質的なことから避けてしまうことこそがより本質的な問題になります。
最初は動かすところから始め、徐々に「きちっとわかる」ようにしていけば良いと思います。あなたの書いたプログラムは一つのプロセス上で動いていて、CPUクロックごとに命令が呼ばれて動いているという非常にシンプルな状態に必ず帰着できます。そういうものだからです。少しづつ基本的なことから実態を伴って理解できるようにしていけばきっとエンジニアとして活躍できるようになると思います。