webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

数学の入門書を選ぶ3つのコツ

微分方程式をしっかりと学んだことが無く、何か手ごろな入門書はないかと本屋さんに出向いたあなたは、きっと驚くはずだ。

微分方程式の入門書はとても多いからだ。さらに、ぱらぱらとめくってみたり、目次を見てみても、中身はほとんど同じだったりする。

これは例え話ではなく、本当に驚くほど同じような書籍が連立している。

線形代数ともなると、さらに多い。

そこで、この記事では、似たような専門書・入門書の中からあなたが欲しいと思う一冊を見つけ出すための3つのコツを紹介する。

これは勉強マニアの私が常に実践しているコツで、この方法を使い始めてからほとんど本の購入に失敗したことが無い。(多くの失敗を重ねてできたノウハウだともいえる)

もちろん、数学でなくても物理学の専門書・入門書を選ぶときでも使える。

【目次】

「はじめに」に注目

まず見てほしいのは、「はじめに」の部分だ。

書籍の目次や内容が同じようでも、「はじめに」の部分にはかなり個性が出る。

「はじめに」にはその書籍がどういった経緯で書かれたのか、対象読者は誰を想定しているのか、どこをゴールとしているのか。

などいわば書籍の自己紹介が書かれている。

その中でも特に注目してほしいのが、対象となる分野の「要約」についてだ。

例えば、微分方程式に関する書籍であれば、微分方程式に関する歴史や現状、エッセンスなどがまとめられていることが多い。

もしこの要約が書かれていなければ、そっとその本を棚に戻すといいだろう。

いくつかの本の「はじめに」に書かれている分野の要約を見ていくと、キラリと光る文章が載っているときがある。

私が見てきた中でいうと、「応用のための関数解析」という関数解析の入門書がそれだ。

新版 応用のための関数解析―その考え方と技法 (SGC BOOKS)

新版 応用のための関数解析―その考え方と技法 (SGC BOOKS)

この書籍の「はじめに」に書かれている分野の要約は、その文章だけでも千円くらいの価値がある素晴らしいものだった。

分野の要約が良いと何がうれしいのかというと、全体を俯瞰したうえで勉強を始められる点にある。

全体を俯瞰した視点を持つと、細かい議論に入っていっても自分がどこにいるのか見失うことはない。これは定理と証明で議論が進められていく数学では特に重要なことだ。

書籍を選ぶときはまず、分野の要約を見て、これから学ぶものの全体像がイメージできるような文章が載っているものを選ぶといいだろう。

ちなみに「はじめに」は書籍の最初だけでなく、各章にも書かれている。その章が何をゴールにしているのかイメージできるというのもとても重要だ。

あなたが得たい知識は「練習問題」にある

さて、あなたが本を買うのは知識やスキルを得たいからであろう。

微分方程式を学びたいという動機で本を買うにしても、人によっては常微分方程式が解けるようになりたいのか、漸近理論が知りたいのか、シミュレーションのために知りたいのかによって選ぶ本が異なってくる。

では、その書籍からどんな知識やスキルを得ることができるのかはどこを見ればいいだろうか。

正解は、「練習問題」に書かれている。

各章の最後にある練習問題は、各章で学んだことだけで(たまに別の知識も必要になることがある)解けるように設定されている。

裏を返せば、その章で取得できることが書かれている。

その章を学べばあなたは練習問題を解く力を得るのだ。

そこで、もし常微分方程式が解けるようになりたいのなら常微分方程式を解く練習問題が載っている入門書を選べばよい。

シミュレーションに応用したいのならコンピュータで解けと書かれている入門書を選ぶといいだろう。

最終的に熱方程式を学びたいのなら最後に熱方程式を解く問題があればいいし、常微分方程式だけでいいなら、最後に偏微分方程式を解く問題が載っている書籍は少し範囲が広すぎる。

私は練習問題を解くことが嫌いだったので、練習問題の内容なんて気にもしなかったし、載っていても解かなかった。

そのことに今となってはすごく後悔しているので、これから数学を学んでいく人はぜひ練習問題をしっかりとこなしてもらいたい。

最初の1割を理解できるか

最後のコツは、本全体の最初の1割がすらすらと読めるかどうかというものだ。

以前、興味だけで「リーマンゼータ函数と保型波動」という書籍を買ったことがあるが、一行目から理解できなかった。

リーマンゼータ函数と保型波動 (共立講座 21世紀の数学 21)

リーマンゼータ函数と保型波動 (共立講座 21世紀の数学 21)

何とか調べながら読み進めようとしたが以降も難しく、結局売ってしまった。

本を買う理由は自分が知らないことを知るためなのだが、全く知らないことだらけだと読むことができない。

そこで、せめて最初の1割または第1章ぐらいはすらすらと読め、おおよそ知っている内容を復習するぐらいの方が全体のバランスはちょうどいい。

1割を超えすぎてしまうと知っていることが長く続き、面白くなくなって、読むのをやめてしまう。

個人差はあると思うが、私の経験からだいたい1割ぐらい既知の内容であるものがちょうどいい

最後に

最近では数学科の学生だけでなく、線形代数や統計学を学ぶ社会人も増えてきた。

数学の専門書は他の経済書や育児本などに比べると平均して千円ほど高い。

書籍一冊にしろ安い買い物ではないし、読むのにも時間がかかるので、ぜひ慎重に選んでから買っていただくことを願いう。

すごいH本のToDoリストのコードを修正する

すごいHaskell楽しく学ぼうという本でHaskellを勉強しているのですが、ToDoリストをもっと楽しむという章に書いてあるコードをそのまま写経して実行してもエラーが出る(コンパイルエラーなので実行もできない)ので、正しいコードを載せておきます。

import System.Environment
import System.Directory
import System.IO
import Data.List
import Control.Exception

dispatch :: String -> [String] -> IO()
dispatch "add" = add
dispatch "view" = view
dispatch "remove" = remove

main = do
  (command:argList) <- getArgs
  dispatch command argList

add :: [String] -> IO()
add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n")

view :: [String] -> IO()
view [fileName] = do
  contents <- readFile fileName
  let todoTasks = lines contents
      numberedTasks = zipWith (\n line -> show n ++ " - " ++ line) [0..] todoTasks
  putStr $ unlines numberedTasks


remove :: [String] -> IO()
remove [fileName, numberString] = do
  contents <- readFile fileName
  let todoTasks = lines contents
      number = read numberString
      newTodoItems = unlines $ delete (todoTasks !! number) todoTasks
  bracketOnError (openTempFile "." "temp")
    (\(tempName, tempHandle) -> do
      hClose tempHandle
      removeFile tempName
    )
    (\(tempName, tempHandle) -> do
      hPutStr tempHandle newTodoItems
      hClose tempHandle
      removeFile fileName
      renameFile tempName fileName
    )
続きを読む

なぜ線形代数ではn次元を学ぶのか

はじめに

理系大学生や機械学習を学ぶ社会人にとって線形代数は必須教科です。

大学に入るとまず習うのが線形代数だし、ディープラーニングの教科書をのぞいてみると線形代数を知っていることが前提に書かれています。

線形代数は簡単に言えば、高校で習ったベクトルの「その先」なのですが、急に次元がn次元に拡張されたことに驚かれるかもしれません。

私たちの住む世界は3次元なのに、なぜn次元なんて必要なんだろう。

そんな疑問を抱いたことはないでしょうか。このページではそんな疑問にお答えします。

続きを読む

【p5.js】transformを正しく理解するためのベクトル・行列講座

Qiita Processing Advent Calendar 2018 12月12日に投稿した記事です

はじめに

scaleやtranlateは書く順番によって結果が異なるって知ってましたか?

本記事は、transform系関数(scale,translate,rotate)を行列で表現し、深く理解することで正しく使えるようになるための講座です。

どのようなときに結果が異なるのか・一致するのか、なぜそのようなことが起こるのか、ベクトルと行列を使ってその謎に迫っていきます。

内容は数学ですが、ベクトルや行列に関する前提知識は必要ありません。ベクトルとは何かから始めていきます。

なぜ行列なのか

Processing(p5js)では線分の開始・終了位置や、円の中心、四角形の四隅など、あらゆる点がx-y座標で表現されています。

座標上の点というのは、言い換えれば原点を始点としたベクトルが指し示す点です。

あるいは、ボールが壁にバウンドするようなアニメーションを考えるときでも、ボールの速度はベクトルで表現されます。

そう、Processingはベクトルで支配されているといっても過言ではないのです。

そんなベクトルを簡単に操作できるツールが行列なのです。

実際、ProcessingにはapplyMatrixという行列を座標全体に作用させる関数が存在します。

そして、scaleやtranslate,rotateなどのtransform系関数はすべてapplyMatrix関数一つで代用が可能なのです。

本記事には華々しいProcessing作品やコードは出てきませんが、Processingの理解はぐっと深まるはずです!

最初は少し退屈かもしれませんが、最後までお付き合いください。

【目次】

  • はじめに
  • なぜ行列なのか
  • ベクトルとは
  • ベクトルの演算
    • 定数倍
    • 三角形の内部を表現する
    • 内積
  • 行列
    • 行列とは
    • 行列の作用
    • translateもscaleもapplyMatrixで書ける
    • 行列の連続作用
  • 行列の合成
    • 行列同士の掛け算
    • 同じ種類の行列であれば可換になる
  • 回転
    • rotate関数
    • その場で回転させたいんだ!
  • まとめ
  • 最後に
  • おまけ
続きを読む

マクローリン展開とテイラー展開と違い

はじめに

先日社内の方が「テイラー展開とマクローリン展開の違いがあるはずだけど、ネットで調べてもよくわからない」と質問していて、それに回答しました。

質問された方から僕の解説が「分かりやすい!」と言っていただけたので、もう少し詳しく説明を加えてブログの方にも書いてみたいと思います。

続きを読む

あなたのWEBコーディング力を向上させる模写参考サイトまとめ

はじめに

Progateドットインストールの登場で、多くの方がhtml&cssの入門されてるのを twitterやブログで見かけるようになりました。

僕もどちらにも登録してます。

ドットインストールでは、htmlやcss, railsなどなど様々なプログラミング言語を学ぶことができます。

Progateではhtml&cssを学びながらサンプルサイトを作っていくことができます。

インプットとしては大枠を上記の2サービスで勉強し、細かいところを書籍などで補えば十分かと思います。

しかし、実務や副業、自分のサイトを作っていくとなると少々アウトプット不足気味なのではないかと思います。

htmlやcssの基礎を学んでも、実際に作りたいサイトを作っていくにはもう少し練習が必要となります。

僕も勉強したての頃は、基礎は学んだけど、いざ作ろうと思ってもどこから始めていいのかわからない、ダサいサイトしか作れない と悩みました。

そこで、今回はwebコーディング最強の勉強法「模写」と模写の参考になるサイトをご紹介します。

続きを読む

エンジニア、アーティスト、学生、主婦。全ての人に届けたいProcessingの魅力

暑さも和らぎ、ようやく僕の大好きな季節「秋」が訪れました。

芸術の秋、食欲の秋、読書の秋・・・

暑くて何もしたくなかった夏が終わって、様々な活動に活発になる時期です。

Processingをご存知でしょうか?

さて、みなさんはProcessingをご存知でしょうか?

Processingはプログラミング学習用として生まれたプログラミング学習ツールです。

図形を描くことを中心機能としているため、多くのアーティストやデザイナーに使われています。ジェネラティブアートなんて言葉を聞いたことがあるかもしれませんね。Processingでは様々なジェネラティブアートが作られています。

最近では、プロアーティストでなくてもエンジニアや工学系学生など、もともとプログラミングできる方が仕事や学問とは別にゲームやアート作品・シミュレーションを作るために使っています。

また、解説本も出版されたり、少しずつブームになりつつあります。

Processing クリエイティブ・コーディング入門 - コードが生み出す創造表現

Processing クリエイティブ・コーディング入門 - コードが生み出す創造表現

p5.jsプログラミングガイド

p5.jsプログラミングガイド

図形を描くための様々な機能がすでに準備されているので、少しプログラミングをかじればすぐに始めることができます。プログラミング初心者でも簡単にアート作品が作れるのです。

慣れてくると、短いものだと5分程度で一つの作品を作ることができます。

f:id:s-uotani-zetakansu:20181009093930p:plain

この他にどんな作品が作れるかは、こちらのサイトをご覧ください。

processing-fan.firebaseapp.com

また、多くのプログラミング言語をサポートしていることもProcessingの大きな特徴です。もともとJavaというプログラミング言語でしか使えなかったのですが、最近ではRuby、Python、JavaScriptなど様々なメジャー言語から使えるようになりました。

エンジニアの方なら新しく言語を覚える必要はなく、一番得意な言語を使うことができます。

エンジニアではなく、プログラミング未経験でも始めてみたいという方に僕が特にお勧めしたいのは、JavaScriptでの開発です。

JavaScriptでの開発は余計なツールのインストールは必要なく、WEBブラウザとメモ帳があれば始められます。近年のJavaScriptの盛り上がりを見れば、JavaScriptの勉強をするという意味でも、JavaScriptで始めてみるのが良いと思います。

それでは、実際にどんなコードでどんな作品が生み出されるのか紹介したいと思います。言語はJavaScriptですが、コードはどの言語でもほとんど同じです。

作品例

No1. Lint

僕が作った中でも最もコード量が短い作品です。

タイトルのLintというのは糸くずのことです。

f:id:s-uotani-zetakansu:20181009095546p:plain

var w = 300;
var h = 300;
//実行後一度だけ処理される初期設定のための関数
function setup() { 
   //描画領域の生成
  createCanvas(w, h);
  // 背景を黒に設定 
  background(0);  
}
// setup処理後、1秒間に60回処理される描画関数
function draw() { 
  // アニメーションではなく静止作品にする
  noLoop();
  //図形の塗りつぶししない 
  noFill(); 
  for(i=0;i<1000;i++){ //1000回{}の中身を繰り返し処理する
    // 空っぽの配列を作る
    var x = new Array(4); 
    for(j = 0; j < 4; j++){
       //ランダムな値を取得
      x[j] = random(); 
    }
     //線の色をランダムに設定
    stroke(color(x[0] * 255,x[1] * 255,x[2] * 255, 30)); 
     // ランダムな点を使ってベジェ曲線を描く
    bezier(w/2, h/2, x[0] * w, x[1] * h, x[2] * w, x[3] * h, w/2, h/2); 
  }
}

No2. Sphere

球体をモチーフにした作品です。

アニメーション作品なので、詳しくはこちらをご覧ください。

draw関数の中身を実行毎に少し変化するようにプログラミングすると、アニメーション作品を作ることができます。

また、スライダーやチェックボックス、プルダウンなどWEBならではのインターフェースも作品に盛り込むこともできます。

f:id:s-uotani-zetakansu:20181009100752p:plain

var w = 400;
var h = 400;
var balls = new Array(1000);
var r = 150;
var select;
function setup() {
  createCanvas(w, h);
  select = createSelect();
  select.position(10,10);
  select.option("Colony");
  select.option("Core");
  select.option("2Core");
  select.option("Surface");
  select.changed(reset);
  reset();
}

function draw() {
  background(0);
  var t = frameCount;
  push();
  translate(w/2,h/2);
  noStroke();
  fill(255, 100);
  for(i=0;i < balls.length;i++){
    var x = balls[i][0] * sin(frameCount / 50 + balls[i][2]);
    var y = balls[i][1];
    ellipse(x, y, 1);
  }
  pop();
}

function reset(){
  var item = select.value();
  for(i=0; i < balls.length;i++){
    if(item === "2Core"){
      var s1 = random([r, r/2,r/3]);
    }else if(item === "Core"){
      var s1 = random([r, r/3]);
    }else if(item === "Surface"){
      var s1 = r;
    }else{
      var s1 = random(r);
    }
    var s2 = TWO_PI/360 * random(360);
    var s3 = TWO_PI/360 * random(360);
    balls[i] = [s1 * cos(s2), s1 * sin(s2), s3, s1];
  }
}

No3. Tidori

妻の「千鳥格子作ってみて」という挑戦状を受け取って作った作品です。

この後、千鳥が飛び立つアニメーション作品も作ったのですが、微妙だったので静止画にしました。

f:id:s-uotani-zetakansu:20181009101015p:plain

var w = 400;
var h = 400;
var triSize = 20;
var miniTriSize = triSize / 2;
var span = triSize * 2;
function setup() {
  createCanvas(w, h);
  background(255);//white
}

function draw() {
  noLoop();
  background(255);
  for(x = 0;x < w;x += span){
    for(y  =0; y < h;y += span){
      push();
      translate(x, y);
      drawTidori();
      pop();
    }
  }
}

function drawTidori(){
  fill(0);
  noStroke();
  triangle(0, triSize, triSize, 0, triSize, triSize);
  rect(triSize, 0, triSize, triSize);
  triangle(triSize, triSize, triSize * 2, triSize, triSize, triSize * 2);
  triangle(triSize * 2, 0, triSize * 2 - miniTriSize, 0, triSize * 2, -miniTriSize);
  triangle(triSize * 2, 0, triSize * 2 + miniTriSize, 0, triSize * 2, miniTriSize);
  fill(255);
  triangle(triSize, triSize, triSize - miniTriSize, triSize, triSize, triSize - miniTriSize);
  triangle(triSize, triSize, triSize + miniTriSize, triSize, triSize, triSize + miniTriSize);
}

No4. Fractal Tree

フラクタルで描いた「木」です。

アートではなくても、数学・物理のシミュレーションなどにも使えます。

processing-fan.firebaseapp.com

この他、熱方程式や波動方程式のシミュレーションも上記のサイトで公開しています。

f:id:s-uotani-zetakansu:20181009102420p:plain

var w = 450;
var h = 400;
var lines = [[w/2, 0, w/2,h]];
var fixedLines = [];
var fixedRate = 3;
var theta;
var newLines = [];
function setup() {
  createCanvas(w, h);
  background(255);//white
  frameRate(2);
  strokeWeight(1);
  theta = TWO_PI / 20;
}

function draw() {
  background(255);
  for(k=0;k < fixedLines.length;k++){
    line(fixedLines[k][0],fixedLines[k][1],fixedLines[k][2],fixedLines[k][3]);
  }
  for(i = 0; i < lines.length; i++){
    line(lines[i][0],lines[i][1],lines[i][2],lines[i][3]);
    lineParts = createLines(lines[i]);
    for(j = 0; j< lineParts.length; j++){
      newLines.push(lineParts[j]);
    }
  }
  lines = newLines;
  newLines = [];
  if(frameCount === 15){
    noLoop();
  }
}

function createLines(l){
  var branchPoint = [(l[0] + l[2] * fixedRate) / (1 + fixedRate), (l[1] + l[3] * fixedRate) / (1 + fixedRate)];

  var fixedLine = [l[2], l[3], branchPoint[0], branchPoint[1]];

  var v1 = l[0] - branchPoint[0];
  var v2 = l[1] - branchPoint[1];

  var u1 = v1 * cos(-theta) - v2 * sin(-theta) + branchPoint[0];
  var u2 = v1 * sin(-theta) + v2 * cos(-theta) + branchPoint[1];
  var l1 = [u1, u2, branchPoint[0], branchPoint[1]];

  var w1 = v1 * cos(theta) - v2 * sin(theta) + branchPoint[0];
  var w2 = v1 * sin(theta) + v2 * cos(theta) + branchPoint[1];
  var l2 = [w1, w2, branchPoint[0], branchPoint[1]];
  
  fixedLines.push(fixedLine);
  return [l1, l2];
}

No5. Halloween

秋、ハロウィンなのでカボチャをモチーフに作りました。

ランダムな位置に出現し、その場で回転します。

こちらもアニメーション作品なのでこちらを見てください。

f:id:s-uotani-zetakansu:20181009101454p:plain

var w = 400;
var h = 400;
var count = 10;
var posi = new Array(count);
function setup() {
  createCanvas(w, h);
  background(0);
  noStroke();
  rectMode(CENTER);
  for(i=0;i < posi.length;i++){
    posi[i] = [random(w), random(h), random(0.2, 0.8)];
  }
}

function draw() {
  background(0);
  for(i=0;i < posi.length;i++){
    push();
    translate(posi[i][0], posi[i][1]);
    rotate(frameCount / (50 * posi[i][2]));
    scale(posi[i][2]);
    drawPumpkin();
    pop();
  }
}

function drawPumpkin(){
  fill(color(255,80,0));
  ellipse(0, 0, 200, 180);
  fill(0);
  ellipse(0,10,170, 140);
  fill(color(255,80,0));
  ellipse(0, -20, 150, 130);
  fill(0);
  triangle(-30,-40,-50,-10,-10,-10);
  triangle(30,-40,50,-10,10,-10);
  fill(color(255,80,0));
  rect(0,75,15,20);
  rect(40,40,15,20);
  rect(-40,40,15,20);
  fill(color(0,255,50));
  rect(0, -105, 15, 30);
}

まとめ

ちょっとProcessingやってみたいなと思っていただけたら幸いです。ほんとに、ちょっと始めてみることができるのもProcessingの魅力です。

僕の運営しているサイトProcessing Fanでは、プログラミング未経験の方でも始められるようにチュートリアルを用意しています。JavaScriptの最初の最初から解説しています。

Processing仲間増やしたいので、興味ある方もない方もぜひ挑戦してみてください。