UNPKG

cejs

Version:

A JavaScript module framework that is simple to use.

316 lines (284 loc) 8.32 kB
/** * @name CeL function for <a * href="http://en.wikipedia.org/wiki/Random_number_generation" * accessdate="2012/3/9 9:36" title="random number generator (RNG)">number * generator</a> * @fileoverview 本檔案包含了生成數字用的 functions。 * @since 2010/1/21 17:58:15 * @example <code> * CeL.run('application.math.number_generator', function() { * // .. * }); * </code> */ 'use strict'; // 'use asm'; // -------------------------------------------------------------------------------------------- // 不採用 if 陳述式,可以避免 Eclipse JSDoc 與 format 多縮排一層。 typeof CeL === 'function' && CeL.run({ name : 'application.math.number_generator', require : 'data.native.to_fixed|data.math.to_rational_number', code : module_code }); function module_code(library_namespace) { // requiring var to_rational_number = this.r('to_rational_number'); if (!Number.prototype.to_fixed) { Number.prototype.to_fixed = library_namespace.to_fixed; } /** * null module constructor * * @class 出數學題目用的 functions */ var _// JSDT:_module_ = function() { // null module constructor }; /** * for JSDT: 有 prototype 才會將之當作 Class */ _// JSDT:_module_ .prototype = {}; _// JSDT:_module_ . /** * 轉換數學式成容易閱讀的形式。 * * @param formula * 數學式. * @param {Boolean}[mode] * 轉換模式. * @returns */ express_formula = function(formula, mode) { if (Array.isArray(formula)) formula = formula.join(''); return _.express_formula.extra[formula] // || (typeof formula === 'string' && formula ? mode // ? formula.replace(/\+/g, '加').replace(/\-/g, '減') // .replace(/\*/g, '乘').replace(/\//g, '除') // : formula.replace(/\s*([+\-*\/])\s*/g, function($0, $1) { return ' ' + { '+' : '+', '-' : '-', '*' : '×', // obelus (symbol: ÷, plural: obeli) '/' : '÷' }[$1] + ' '; }) : ''); }; _// JSDT:_module_ .express_formula.extra = { '+-*/' : '四則', // [Mathematics] to find a common denominator / the lowest common // denominator f_cd : '通分', reduction : '約分', converting_mixed : '代換(假分數←→帶分數)', compare_size : '比大小', with_decimal : '與小數運算' }; /** * http://163.32.181.11/ymt91050/m/%E6%95%B8%E5%AD%B8%E7%B7%B4%E7%BF%92%E9%A1%8C.htm * http://webmail.ysps.tp.edu.tw/~wenji/material.htm * * 一位小數加法(直式) * * 一位小數減法(橫式) */ _// JSDT:_module_ . /** * 將問題 pattern 中的 '??' 等轉成實際數字,生成實際問題。 * * @param {String}problem_pattern * problem pattern. e.g., '???.??', '[??/?]', 可用 + - * /. * @param {Integer}method * method. 1: 只是要取得亂數. 2: 取得整個數值的亂數. others: 產出整個題目。 * @returns */ parse_problem = function(problem_pattern, method) { if (typeof problem_pattern !== 'string' || !problem_pattern) return problem_pattern; var _s = _.parse_problem, /** * gn: generate number */ gn = function(n, z) { /** * z: can start with zero */ if (!z) n = n.replace(/\?/, function($0) { return 1 + Math.floor(Math.random() * 9); }); return n.replace(/\?/g, function($0) { return Math.floor(Math.random() * 10); }); }, gn2 = function(n) { return n.replace( /(\?*|0)\.(\?+)/g, function($0, $1, $2) { return ($1.indexOf('?') === -1 ? '0' : gn($1)) + '.' + gn($2, 1); }).replace(/\?+/g, function($0) { return gn($0); }); }; if (false && !problem_pattern // .match(/^(((\?*|0)\.)?\?+|[+\-*\/]|\s){3,}$/)) library_namespace.debug('No match: ' + problem_pattern); problem_pattern = problem_pattern.replace(/\[((\d\-\d|\d+)+)\]/g, // function($0, $1) { var n = $1.replace(/(\d)\-(\d)/g, function($0, $1, $2) { var i = Math.min($1, $2), n = '', M = Math.max($1, $2); for (; i < M; i++) n += i; return n; }); return n.charAt(Math.floor(Math.random() * n.length)); }).replace(/(\d)(\?+)/g, function($0, $1, $2) { return $1 + gn($2, 1); }); problem_pattern = gn2(problem_pattern); // method === 1: 只是要取得亂數 return method === 1 ? problem_pattern // method === 2: 取得整個數值的亂數 : method === 2 ? problem_pattern.replace(/0+$|^0+/g, '') : _s .express(problem_pattern); }; _// JSDT:_module_ .parse_problem.express = function(q) { return typeof q !== 'string' ? [ q, q ] // : [ q.replace(/\/\//g, '/') // .replace(/\s*÷\s*/g, '/').replace(/\s*×\s*/g, '*') // .replace(/\s*=+\s*/g, '===') , q.replace(/\/\//g, '\\').replace(/[+\-*\/]/g, function($0) { return _.express_formula($0); }).replace(/\\/g, '/') ]; }; _// JSDT:_module_ . /** * 隨機生成 count 個不同之數字。 * * @param {String}pattern * 生成數字之 pattern * @param {Number}count * 生成個數,預設 2。僅要一個時直接 call .parse_problem() 即可。 * @param {Function}comparator * 回傳以 comparator 排序後的數列。 * @return {Array} [numbers] 排序過之數字 */ get_different_numbers = function(pattern, count, comparator) { if (!count || isNaN(count)) count = 2; var i = 0, s, seeds = [], seed_hash = {}, limit; for (; i < count; i++) { limit = 50; while (limit-- // && (!(s = parseFloat(_.parse_problem(pattern, 1)).to_fixed()) // || (s in seed_hash))) ; if (!limit) { library_namespace .warn('Fault to generate number using pattern [' + pattern + ']!'); } seeds.push(s); seed_hash[s] = i; } if (comparator) { library_namespace.is_Function(comparator) ? seeds.sort(comparator) : seeds.sort(); } return seeds; }; _// JSDT:_module_ . /** * 演算解答. * * @param {String}problem * problem * @returns {String}answer in float, (帶)分數, .. * @see data.math.quotient */ evaluate_value = function(problem) { // if(!isNaN(problem))return problem; if (!problem) return; problem = _.parse_problem.express(String(problem))[0]; var answer, m = problem.match(/^(\d+(\.\d+)?)\/(\d+)$/); function adding(v) { if (v !== Math.floor(v)) { m = to_rational_number(v); // 處理真分數、假分數。 answer += ' ' // 約等於的符號是≈或≒,不等於的符號是≠。 + (m[2] < 1e-13 ? ' = ' : ' <span title="大約">≈</span> ') // http://zh.wikipedia.org/wiki/%E7%AD%89%E4%BA%8E + '<span class="fraction">' + m[0] + ' / ' + m[1] + '</span>'; // 處理帶分數。 mixed numeral (often called a mixed number, also // called a mixed fraction) if (m[0] >= m[1]) { problem = m[0] % m[1]; answer += ' = <span class="mixed_numeral">' // + (m[0] - problem) / m[1] // + ' + ' + problem + ' / ' + m[1] + '</span>'; } } } if (m) { answer = Math.floor(m[1] / m[3]).to_fixed(12) + ' ... ' // + (m[1] % m[3]).to_fixed() // + (m[1] % m[3] ? ' <span title="大約">≈</span> ' // + (m[1] / m[3]).to_fixed() : ''), adding(m[1] / m[3]); } else { try { // 直接執行 // 須預防 6/2/3 的情況 m = 'return(' + problem.replace(/(\d+)\s+(\d+\/\d+)/g, '($1+$2)') + '\n)'; m = (new Function(m))(); if (false) { library_namespace.debug('{return(' + problem.replace(/(\d+)\s+(\d+\/\d+)/g, '($1+$2)') + ');}' + ' = ' + m); } if (isNaN(m)) { library_namespace .warn('evaluate_value: No problem generated for [' + problem + '].'); } else { answer = m.to_fixed(); adding(m); } } catch (e) { library_namespace.warn('evaluate_value: 無法演算 [' + problem + '] (' + m + '). ' + e); answer = '`' + problem + '`'; } } return answer; }; return (_// JSDT:_module_ ); }