開発環境
- macOS Sierra - Apple (OS)
- Emacs (Text Editor)
- JavaScript (プログラミング言語)
- JavaScript Library
- Safari(Web browser)
- 参考書籍
- JavaScript 第6版 (David Flanagan(著)、村上 列(翻訳)、オライリージャパン)
- JavaScriptリファレンス 第6版(David Flanagan(著)、木下 哲也(翻訳)、オライリージャパン)
計算機プログラムの構造と解釈[第2版](ハロルド エイブルソン (著)、ジュリー サスマン (著)、ジェラルド・ジェイ サスマン (著)、Harold Abelson (原著)、Julie Sussman (原著)、Gerald Jay Sussman (原著)、和田 英一 (翻訳)、翔泳社、原著: Structure and Interpretation of Computer Programs (MIT Electrical Engineering and Computer Science)(SICP))の第1章(手続きによる抽象の構築)、1.3(高階手続きによる抽象)、1.3.4(値として返される手続き)、問題1.40.を JavaScript で取り組んでみる。
その他参考書籍
問題1.40.
コード(Emacs)
HTML5
<math> <mrow> <mi>f</mi><mrow><mo>(</mo> <mi>x</mi> <mo>)</mo></mrow><mo>=</mo><msup> <mi>x</mi> <mn>3</mn> </msup> <mo>+</mo><mi>a</mi><msup> <mi>x</mi> <mn>2</mn> </msup> <mo>+</mo><mi>b</mi><mi>x</mi><mo>+</mo><mi>c</mi> </mrow> </math> <script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <div id="graph0"></div> <div id="xs0"></div> <label for="a0">a = </label> <input id="a0" type="number" step="1" value="1"> <label for="b0">b = </label> <input id="b0" type="number" step="1" value="2"> <label for="c0">c = </label> <input id="c0" type="number" step="1" value="3"> <label for="guess0">予測値: </label> <input id="guess0" type="number" step="1" value="1"> 零点の近似: f(<span id="zero0"></span>) = <span id="fx0"></span> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script> <script src="sample40.js"></script>
JavaScript
{ 'use strict'; Array.range = function (start, end, step) { var nums = [], i; if (step === 0) { throw { name: 'ValueError', message: 'range() arg 3 must not be zero', }; } if (step === undefined) { step = 1; } if (end === undefined) { end = start; start = 0; } if (step > 0) { for (i = start; i < end; i += step) { nums.push(i); } } else { for (i = start; i > end; i += step) { nums.push(i); } } return nums; }; let svg, width = 600, height = 600, padding = 50, xscale, yscale, min, max, xaxis, yaxis, div_graph = document.querySelector('#graph0'), div_xs = document.querySelector('#xs0'), input_a = document.querySelector('#a0'), input_b = document.querySelector('#b0'), input_c = document.querySelector('#c0'), input_guess = document.querySelector('#guess0'), inputs = [input_a, input_b, input_c, input_guess], span_zero = document.querySelector('#zero0'), span_fx = document.querySelector('#fx0'), tolerance = 0.00001, xs, ys, fixedPoint = (f, first_guess) => { let isCloseEnough = (v1, v2) => { return Math.abs(v1 - v2) < tolerance; }; xs = [first_guess]; let tryFunc = (guess) => { let next = f(guess); xs.push(next); if (isCloseEnough(guess, next)) { return next; } return tryFunc(next); }; return tryFunc(first_guess); }, dx = 0.00001, deriv = (g) => { return (x) => (g(x + dx) - g(x)) / dx; }, newtonsTransform = (g) => { return (x) => x - g(x) / deriv(g)(x); }, newtonsMethod = (g, guess) => fixedPoint(newtonsTransform(g), guess), cubic = (a, b, c) => { return (x) => Math.pow(x, 3) + a * Math.pow(x, 2) + b * x + c; }, output = () => { let a = parseFloat(input_a.value), b = parseFloat(input_b.value), c = parseFloat(input_c.value), guess = parseFloat(input_guess.value), x = newtonsMethod(cubic(a, b, c), guess); span_zero.innerText = x; div_xs.innerHTML = `収束の様子<br>${xs.join('<br>')}`; let func = cubic(a, b, c); ys = xs.map(func); span_fx.innerText = ys[ys.length - 1]; max = Math.max.apply(null, xs.concat(ys).map(Math.abs)); min = -max; let points = Array.range(min, max, 0.01) .map((x) => [x, func(x), 1, 'blue']) .filter((point) => min < point[1] && point[1] < max); xscale = d3.scaleLinear() .domain([min, max]) .range([padding, width - padding]); yscale = d3.scaleLinear() .domain([min, max]) .range([height - padding, padding]); xaxis = d3.axisBottom().scale(xscale); yaxis = d3.axisLeft().scale(yscale); points = points.map((point) => [xscale(point[0]), yscale(point[1]), point[2], point[3]]) .concat(xs.map((x, i) => { return [xscale(x), yscale(ys[i]), 4, 'green']; })); div_graph.innerHTML = ''; svg = d3.select('#graph0') .append('svg') .attr('width', width) .attr('height', height); svg.selectAll('circle') .data(points) .enter() .append('circle') .attr('cx', (d) => d[0]) .attr('cy', (d) => d[1]) .attr('r', (d) => d[2]) .attr('fill', (d) => d[3]); svg.append('line') .attr('x1', xscale(min)) .attr('y1', yscale(0)) .attr('x2', xscale(max)) .attr('y2', yscale(0)) .attr('stroke', 'black'); svg.append('g') .attr('transform', `translate(0, ${height / 2})`) .call(xaxis); svg.append('g') .attr('transform', `translate(${width / 2}, 0)`) .call(yaxis); }; inputs.forEach((input) => { input.onchange = output; }); output(); }零点の近似: f() =
0 コメント:
コメントを投稿