diff --git a/frontend/js/trainer/_trainer_engine.js b/frontend/js/trainer/_trainer_engine.js index 4276dec..05d9b97 100644 --- a/frontend/js/trainer/_trainer_engine.js +++ b/frontend/js/trainer/_trainer_engine.js @@ -160,6 +160,11 @@ var s = _latex(node); return _prec(node) < minPrec ? '\\left(' + s + '\\right)' : s; } + // «числовой множитель»: число, константа или степень с числовым основанием (2, 7^2). + // Между двумя такими ставим ·, иначе адъяцентность «2·7²» прочитается как «27²». + function _isNumFactor(n) { + return n.k === 'num' || n.k === 'const' || (n.k === 'bin' && n.op === '^' && _isNumFactor(n.a)); + } // Операнд умножения: отрицательное/унарное/сумму берём в скобки, иначе // соседство схлопнет смысл (7*(-5) -> «7-5», 6*(x+1) -> «6x+1»). function _mulOperand(node) { @@ -197,6 +202,8 @@ if (op === '/') return '\\frac{' + _latex(node.a) + '}{' + _latex(node.b) + '}'; if (op === '^') { var base = _prec(node.a) < 5 ? '\\left(' + _latex(node.a) + '\\right)' : _latex(node.a); + if (node.b.k === 'num' && node.b.v === 1) return base; // x^1 -> x + if (node.b.k === 'num' && node.b.v === 0) return '1'; // x^0 -> 1 return base + '^{' + _latex(node.b) + '}'; } if (op === '*') { @@ -206,7 +213,8 @@ if (node.b.k === 'num' && Math.abs(node.b.v) === 1 && node.a.k !== 'num') return (node.b.v < 0 ? '-' : '') + _mulOperand(node.a); if (_isNeg(node.a)) return '-' + _latex({ k: 'bin', op: '*', a: _negate(node.a), b: node.b }); // -5*x -> «-5x» - var sep = (node.b.k === 'num' && node.b.v >= 0) ? ' \\cdot ' : ''; // знак · между числами; иначе соседство + // · между числами и числовыми множителями (2·3, 2·7²); иначе соседство (2x, 3(x+1)) + var sep = ((node.b.k === 'num' && node.b.v >= 0) || (_isNumFactor(node.a) && _isNumFactor(node.b))) ? ' \\cdot ' : ''; return _mulOperand(node.a) + sep + _mulOperand(node.b); } if (op === '%') return _wrapL(node.a, 2) + ' \\bmod ' + _wrapL(node.b, 3); diff --git a/frontend/js/trainer/generators.js b/frontend/js/trainer/generators.js index 83e8d27..9d53543 100644 --- a/frontend/js/trainer/generators.js +++ b/frontend/js/trainer/generators.js @@ -835,34 +835,57 @@ }, /* ═══ Тема: НОД и НОК (5–6 класс) ═══ - Числа строим как g·m и g·k (общий множитель g) → НОД ≥ g, не тривиален. - gcd/lcm — функции SimExpr (алгоритм Евклида), считаются и проверяются движком. */ + Оба числа строим из ДВУХ простых множителей p