/** * @name CeL function for math application. * @fileoverview * 本檔案包含了生成 math application 的 functions。 * @since 2014/10/3 * @example * * CeL.run('application.math', function() { * // .. * }); * */ 'use strict'; if (typeof CeL === 'function') CeL.run( { name : 'application.math', // includes() @ data.code.compatibility. require : 'data.code.compatibility.|data.math.', code : function module_code(library_namespace) { /** * null module constructor * @class 出數學題目用的 functions */ var _// JSDT:_module_ = function() { // null module constructor }; /** * for JSDT: 有 prototype 才會將之當作 Class */ _// JSDT:_module_ .prototype = { }; //----------------------------------------------------- // (function() { runCode.setR = 0; for (var i = 0, j, t, s, n_e; i < 10;) { t = 2000 + 8000 * Math.random(); s = get_random_prime.get_different_number_set(3, t, t / 8); if (s.LCM > 9999) continue; n_e = []; n_e[s.GCD] = 1; for (j = 0; j < s.length; j++) if (n_e[s[j]]) continue; else n_e[s[j]] = 1; sl([ s.GCD, s.LCM ] + '; ' + s); i++; } }); //----------------------------------------------------- // // 中式短除法(Chinese short division)並非 short division. // https://en.wikipedia.org/wiki/Short_division function draw_short_division(naturals, layer, GCD_only) { if (!Array.isArray(naturals)) if (isNaN(layer)) naturals = [ naturals ]; else naturals = arguments, layer = null; var i, length = naturals.length | 0, divisor, cell_width_em = 2, // natural_Array = []; for (i = 0; i < length; i++) { divisor = +naturals[i]; if (0 < divisor && divisor < Number.MAX_SAFE_INTEGER) { natural_Array.push(divisor); if (cell_width_em < String(divisor).length * .6) cell_width_em = Math.ceil(String(divisor).length * .6); } } length = (naturals = Array.prototype.slice.call(natural_Array)).length | 0; var block = [], count = 0, // _GCD = library_namespace.GCD(natural_Array), // GCD = library_namespace.factorize(_GCD); library_namespace.debug(length + ' Naturals: '+natural_Array+'.',2); if (GCD) { // assert: _GCD > 1 if (_GCD !== (divisor = GCD.toString(true))) _GCD += ' = ' + divisor; // phase 1: 處理 GCD 部分。 for (divisor in GCD) { divisor |= 0; for (var j = 0; j < GCD[divisor] | 0; j++) if (length !== 1 || natural_Array[0] !== divisor) { block.push(draw_short_division.add_line(natural_Array, cell_width_em, divisor, count++, true)); for (i = 0; i < length; i++) natural_Array[i] = natural_Array[i] / divisor; } } } // phase 2: 處理 LCM 部分。 // TODO: 按大小排列。 GCD = 0; do { var LCM = natural_Array[0]; for (i = 1; i < length; i++) if (natural_Array[i] > 1 && (GCD = library_namespace.GCD(LCM, natural_Array[i])) > 1) { divisor = +library_namespace.first_factor(GCD); block.push(draw_short_division.add_line(natural_Array, cell_width_em, divisor, count++)); for (i = 0; i < length; i++) if (natural_Array[i] % divisor === 0) natural_Array[i] = natural_Array[i] / divisor; break; } } while (GCD > 1); // 依照各種不同類之輸入,顯示不同備註標示。 if (length === 1) { // 質因數分解。 block.push( draw_short_division.add_line(natural_Array, cell_width_em), { div: [ _GCD ] } ); } else { i = library_namespace.LCM(naturals); block.push( draw_short_division.add_line(natural_Array, cell_width_em), { div: [ 'GCD', // '(', naturals.join(', '), ')', ' = ', _GCD ], S: draw_short_division.GCD_style }, { div: [ 'LCM', // '(', naturals.join(', '), ')', ' = ', i, ' = ', library_namespace.factorize(i).toString(true) ] } ); } // 最後收尾。 block = { div: block, style: 'width:' + (1 + (length + (1 < length ? 2 : 1)) * cell_width_em | 0) + 'em;background-color:#def', C: 'short_division' }; return layer ? new_node(block, layer) : block; } draw_short_division.GCD_style = 'color:#f79;'; draw_short_division.add_line = function(naturals, cell_width_em, divisor, count, phase_GCD) { library_namespace.debug(divisor + ': ' + naturals, 3, 'draw_short_division.add_line'); var line = []; naturals.forEach(function(natural, index) { line.push({ span: natural, S: 'display:inline-block;text-align:right;padding-right:.2em;width:' + (cell_width_em + (index ? 0 : .5 - count / 5)).to_fixed(2) + 'em' }, ' '); }); line.pop(); if (divisor) line = [{ span: divisor, S: 'text-align:right;padding-right:.2em;' }, { span: line, S: 'border-left:1pt solid #88f;border-bottom:1pt solid #88f' }]; return { div: line, S: 'clear:both;text-align:right;' + (phase_GCD ? draw_short_division.GCD_style : '') }; }; _.draw_short_division = draw_short_division; /* CeL.run('application.math', function() { CeL.draw_short_division([12], [ document.body, 2 ]); CeL.draw_short_division([12, 18], [ document.body, 2 ]); CeL.draw_short_division([12, 18, 24], [ document.body, 2 ]); }); */ // ---------------------------------------------------------------------------------------------- // var new_node = function () { var func = library_namespace.DOM.new_node; if (func) return (new_node = func).apply(null, arguments); }, // check_MathML = function() { var math_node = new_node({ div : { span : 'normal' }, S : 'line-height:1em;visibility:hidden' }, document.body); if (!math_node) return; new_node({ math : { mfrac : [ { mi : 'test' }, { mi : 'MathML' } ] } }, math_node, 'mathml'); // Firefox/37.0 不需要 setTimeout()。 // setTimeout(check_MathML.check.bind(math_node), 0); // return check_MathML.check.call(math_node, true); return check_MathML.check.call(math_node); }; // 2015/1/1: Firefox only. 僅 firefox 回傳 true。 check_MathML.check = function(no_remove) { // library_namespace.debug(this); Object.defineProperty(_, 'support_MathML', { // method 1: // 分數 2/3 之 2 的 offsetTop 應該比 3 更高一點。 // 但在 ff 中,沒有 .offsetTop。 // var mfrac = this.lastChild.firstChild; // value : mfrac.firstChild.offsetTop < mfrac.lastChild.offsetTop; // method 2: 因為插入
應該比一般單行文字更高一點。但在 Chrome,兩者本身即有差別。 value : this.offsetHeight > this.firstChild.offsetHeight + 3 }); if (!_.support_MathML) library_namespace.debug('The browser does not support MathML. 您的瀏覽器不支援 MathML,或是 MathML 功能已被關閉。'); if (no_remove !== true) { // library_namespace.remove_node(this); document.body.removeChild(this); } return _.support_MathML; }; // assert: support MathML 也必定 support Object.defineProperty(). Object.defineProperty(_, 'support_MathML', { configurable : true, get : check_MathML }); // ----------------------------------------------------- // /** * 以 MathML 表現數學運算式。
* 將 HTML 中 <math>expression</math> 皆轉為 MathML。
* parse math expression & output MathML.
* * TODO: calculator, vector, ℕℤℚℝℂ, ∈∉ * * @example //