+ Ответить в теме
Показано с 1 по 4 из 4

Тема: деградационная математика

  1. #1
    Местный Degradator на пути к лучшему Аватар для Degradator
    Регистрация
    02.07.2012
    Сообщений
    1,905
    Thanks
    141
    Thanked 142 Times in 142 Posts

    деградационная математика

    Всем привет, тут я буду писать всякие javascript'ы.
    Начну с решения линейных уравнений

    ax + b = 0;


    для того чтобы написать решение уравнения, напишем класс

    function LinearEquation() {
    this.a = 0;
    this.b = 0;
    }
    LinearEquation.prototype.solve = function() {
    if(this.a === 0) {
    return [NaN];
    }
    return [-this.b / this.a];
    }
    LinearEquation.prototype.setA = function(a) {
    this._validateArgument(a);
    this.a = a;
    }
    LinearEquation.prototype.getA = function() {
    return this.a;
    }
    LinearEquation.prototype.setB = function(b) {
    this._validateArgument(b);
    this.b = b;
    }
    LinearEquation.prototype.getB = function() {
    return this.b;
    }
    LinearEquation.prototype._validateArgument= function(argument) {
    if(typeof argument !== 'number' || isNaN(argument)) {
    throw "Argument is not a number";
    }
    }


    Проверим как работает


    var linearEquation = new LinearEquation();
    linearEquation.setA(10);
    linearEquation.setB(-50);
    console.log(linearEquation.solve());


    Итак, при

    10 * x - 50 = 0


    код выводит что искомое будет равно 5. Вроде бы все правильно. Смотрим в пример. Итого у нас есть класс с двумя полями, геттерами-сеттерами, функцией solve и функцией _validateArgument. Как можно заметить функция solve возвращает массив. Это сделано для того, чтобы в дальнейшем можно было написать функцию для квадратных уравнений, которая будет возвращать массив из двух элементов. Кроме этого, функция solve исключает деление на 0, и возвращает массив со значением NaN (not a number), в этом случае - неопределенность. Функция _validateArgument имеет нижнее подчеркивание вначале. Такое нижнее подчеркивание дает знать, что эта функция сделана для служебного пользования, что-то типа модификатора доступа protected. Говорят, что двойное нижнее подчеркивание значит private, но в своей практике двойное нижнее подчеркивание в названиях функций я никогда не видел.

    Следующей задачей будет написание функции, с входным аргументом в виде строки. В этой строке будет записано линейное уравнение, и эта процедура должна будет посчитать его.
    Последний раз редактировалось Degradator; 18.05.2018 в 19:38.

  2. #2
    Местный Degradator на пути к лучшему Аватар для Degradator
    Регистрация
    02.07.2012
    Сообщений
    1,905
    Thanks
    141
    Thanked 142 Times in 142 Posts
    Итак, пишем парсер выражения. Он должен разобрать первое попавшееся выражение, будь то число или неизвестное, и сохранить курсор.


    function Variable () {
    this.value = null;
    }
    Variable.prototype.getValue = function () {
    return this.value;
    };
    Variable.prototype.setValue = function (value) {
    return this.value = value;
    };


    function VariableParser(expression, cursor) {
    this.cursor = cursor;
    this.expression = expression;
    this.variable = null;
    this._parse();
    }
    VariableParser.IS_NUMBER = 1;
    VariableParser.NOT_A_NUMBER = -1;
    VariableParser.NUMBER_PARSER = /^(-?\s*\d+\.?\d*)/;
    VariableParser.CHAR_PARSER = /^(-?\s*[a-zA-Z])/;
    VariableParser.WHITESPACE_LEFT = /^\s*/;
    VariableParser.WHITESPACE_RIGHT = /\s*$/;

    VariableParser.prototype.toString = function() {
    return "Variable: " + this.getVariable().getValue() + "; cursor: " + this.getCursor();
    };
    VariableParser.prototype.getCursor = function() {
    return this.cursor;
    };
    VariableParser.prototype.getExpression = function() {
    return this.expression;
    };
    VariableParser.prototype.getVariable = function() {
    return this.variable;
    };



    VariableParser.prototype._parse = function() {
    var expression = this.expression;
    if(typeof expression !== 'string') {
    throw "Expression is not a string";
    }
    var trimResult = this._trim(expression);
    expression = trimResult.expression;
    if(expression.length === 0) {
    throw "Expression is empty";
    }

    var rawData = null;
    var variableType;
    if(expression.match(VariableParser.NUMBER_PARSER) !== null) {
    variableType = VariableParser.IS_NUMBER;
    rawData = VariableParser.NUMBER_PARSER.exec(expression);
    } else {
    variableType = VariableParser.NOT_A_NUMBER;
    rawData = VariableParser.CHAR_PARSER.exec(expression);
    }
    if(rawData === null || rawData.length < 2) {
    throw "Can't parse expression";
    }
    var subExpression = rawData[1];
    this.cursor = trimResult.left + subExpression.length;

    var multiplier = 1;
    if(subExpression.indexOf("-") === 0) {
    multiplier = -1;
    subExpression = subExpression.substring(1);
    }
    var variable = new Variable();
    subExpression = subExpression.trim();
    if(variableType === VariableParser.IS_NUMBER) {
    subExpression = parseFloat(subExpression) * multiplier;
    } else {
    if(multiplier === -1) {
    subExpression = "-" + subExpression;
    }
    }
    variable.setValue(subExpression);
    this.variable = variable;
    };

    VariableParser.prototype._trim = function(expression) {
    var leftMatch = VariableParser.WHITESPACE_LEFT.exec(expression);
    var rightMatch = VariableParser.WHITESPACE_RIGHT.exec(expression);
    return {
    expression: expression.trim(),
    left: leftMatch && leftMatch[0].length > 0 ? leftMatch[0].length : 0,
    right: rightMatch && rightMatch[0].length > 0 ? rightMatch[0].length : 0,
    total: expression.length
    }
    };


    проверяем работу:

    ["20x = 0",
    "x = 0",
    " x = 0",
    " 20 x = 0",
    "-20x = 0",
    " -20x = 0",
    " - x = 0"].forEach(v => console.log((new VariableParser(v, 0)).toString()));


    Отлично работает. Теперь надо написать класс, который будет угадывать какое математическое действие следует выбрать для дальнейших вычислений
    Последний раз редактировалось Degradator; 25.05.2018 в 13:02.

  3. #3
    Местный Degradator на пути к лучшему Аватар для Degradator
    Регистрация
    02.07.2012
    Сообщений
    1,905
    Thanks
    141
    Thanked 142 Times in 142 Posts
    В предыдущем посте я отредактировал конструктор VariableParser, теперь он хочет принимать курсор. Это сделано для дальнейшего парсинга выражения.
    Раздумываю над тем, как продолжить вычиления, прихожу к выводу, что надо делать какую-то chain конструкцию.
    Хотелось бы чтобы было примерно так
    variable1.multiple(variable2).plus(variable3).equals(0);

    Но не хочется захломлять класс variable. Наверно надо сделать класс Equation, который будет работать так
    Equation.start(variable1).multiple(variable2).plus(variable3).equals(0);

    В дальнейшем надо будет дописать класс SubEquation который будет нести примерно такойже смысл как скобки.

  4. #4
    Местный Degradator на пути к лучшему Аватар для Degradator
    Регистрация
    02.07.2012
    Сообщений
    1,905
    Thanks
    141
    Thanked 142 Times in 142 Posts
    в дальнейшем знаки мат действий надо будет заменить на классы. Пока что так




    function Equation() {
    this.variables = [];
    this.actions = [];
    this.pointer = -1;
    this.isClosed = false;
    this.isBlock = false;
    }
    Equation.prototype.start = function(variable) {
    this._variableCheck(variable);
    this.variables.push(variable);
    this.pointer = 0;
    };
    Equation.prototype.sum = function(variable) {
    this._action(variable, '+');
    };
    Equation.prototype.substract = function(variable) {
    this._action(variable, '-');
    };
    Equation.prototype.multiple = function(variable) {
    this._action(variable, '*');
    };
    Equation.prototype.divide = function(variable) {
    this._action(variable, '/');
    };
    Equation.prototype.close = function(variable) {
    this.isClosed = true;
    this.isBlock = true;
    };
    Equation.prototype.equals = function(variable) {
    this._action(variable, '=');
    this.isClosed = true;
    this.isBlock = false;
    };
    Equation.prototype._action = function(variable, action) {
    this._variableCheck(variable);
    this.variables.push(variable);
    this.actions.push(action);
    this.pointer++;
    };
    Equation.prototype._variableCheck = function(variable) {
    if(!(variable instanceof Variable)) {
    throw "Invalid arguments exception, should be instance of Variable";
    }
    };

+ Ответить в теме

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения