2016年9月13日火曜日

開発環境

計算機プログラムの構造と解釈[第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.1(引数としての手続き)、問題1.31.をJavaScript取り組んでみる。

その他参考書籍

問題1.31.

コード(Emacs)

HTML5

<label for="ifactorial0">
  factorial0(
</label>
<input id="ifactorial0" type="number" min="0" step="1" value="10">
) = <span id="ofactorial0"></span>
<br>
<label for="ipi0">
  pi0(
</label>
<input id="ipi0" type="number" min="0" step="1" value="100">
) = <span id="opi0"></span>
<br>
<label for="ifactorial1">
  factorial1(
</label>
<input id="ifactorial1" type="number" min="1" value="10">
) = <span id="ofactorial1"></span>
<br>
<label for="ipi1">
  pi1(
</label>
<input id="ipi1" type="number" min="0" step="1" value="100">
) = <span id="opi1"></span>
<br>

<script src="temp.js"></script>

JavaScript

(function () {
    'use strict';
    var product0,
        product1,
        id,
        inc,
        factorial0,
        factorial1,
        pi0,
        pi1,
        square,

        input_factorial0 = document.querySelector('#ifactorial0'),
        input_factorial1 = document.querySelector('#ifactorial1'),
        input_pi0 = document.querySelector('#ipi0'),
        input_pi1 = document.querySelector('#ipi1'),
        inputs = [input_factorial0, input_factorial1, input_pi0, input_pi1],
        span_factorial0 = document.querySelector('#ofactorial0'),    
        span_factorial1 = document.querySelector('#ofactorial1'),
        span_pi0 = document.querySelector('#opi0'),
        span_pi1 = document.querySelector('#opi1'),
        output_factorial0,
        output_factorial1,
        output_pi0,
        output_pi1;

    id = function (x) {
        return x;
    };
    inc = function (x) {
        return x + 1;
    };
    square = function (x) {
        return Math.pow(x, 2);
    };

    product0 = function (term, a, next, b) {
        if (a > b) {
            return 1;
        }
        return term(a) * product0(term, next(a), next, b);
    };
    factorial0 = function (n) {
        return product0(id, 1, inc, n);
    };
    pi0 = function (n) {
        return 4 * product0(
            function (n) {
                return (2 * n + 2) * (2 * n + 4) / square(2 * n + 3);
            },
            0,
            inc,
            n);
    };

    product1 = function (term, a, next, b) {
        var iter;

        iter = function (a, result) {
            if (a > b) {
                return result;
            }
            return iter(next(a), term(a) * result);
        };
        return iter(a, 1);
    };

    factorial1 = function (n) {
        return product1(id, 1, inc, n);
    };
    pi1 = function (n) {
        return 4 * product1(
            function (n) {
                return (2 * n + 2) * (2 * n + 4) / square(2 * n + 3);
            },
            0,
            inc,
            n);
    };
    output_factorial0 = function () {
        var n = parseInt(input_factorial0.value, 10);

        try {
            span_factorial0.innerText = factorial0(n);
        } catch(e) {
            span_factorial0.innerText = e.message;
        }
    };
    output_pi0 = function () {
        var n = parseInt(input_pi0.value, 10);

        try {
            span_pi0.innerText = pi0(n);
        } catch(e) {
            span_pi0.innerText = e.message;
        }
    };
    output_factorial1 = function () {
        var n = parseInt(input_factorial1.value, 10);

        try {
            span_factorial1.innerText = factorial1(n);
        } catch(e) {
            span_factorial1.innerText = e.message;
        }
    };
    output_pi1 = function () {
        var n = parseInt(input_pi1.value, 10);

        try {
            span_pi1.innerText = pi1(n);
        } catch(e) {
            span_pi1.innerText = e.message;
        }
    };
    input_factorial0.onchange = output_factorial0;
    input_factorial1.onchange = output_factorial1;
    input_pi0.onchange = output_pi0;
    input_pi1.onchange = output_pi1;

    [output_factorial0, output_factorial1,
     output_pi0, output_pi1].forEach(function (output) {
         output();
     });
}());

今のところ、数値を大きくすると例外(Maximum call stack size exceeded. ) 発生。proper tail callsが実装されれば、例外派生せずにすみそう。

kjs-math-number (JavaScript Library) を使えば、Infinity も避けられるけど、今回は速度優先で。

) =
) =
) =
) =

0 コメント:

コメントを投稿