Вопрос

МИКСИН MONEYUTILSMIXIN (МЕТОД GETPERCENTAGEPART)

Коллеги изучаю документацию по разработке. (конкретно с миксин MONEYUTILSMIXIN, а МЕТОД GETPERCENTAGEPART)

https://academy.terrasoft.ru/documents/technic-sdk/7-13/miksin-moneyutilsmixin

Прошу помощи знающих коллег. 

!!результат данного метода получают так. 

taxAmount = this.getPercentagePart(totalAmount, discountTax);

тут мне все понятно :)

Мой вопрос почему именно метод GETPERCENTAGEPART в MONEYUTILSMIXIN  реализован именно так? 

 

 

/**

         * Calculates percent part of whole value by given percent.

         * example:

         * amount = 10, percent = 20, result = 2 (2 is 20% of 10).

         * @param {Number} amount Total value.

         * @param {Number} percent Partial percent .

         * @returns {Number}

         */

        getPercentagePart: function(amount, percent) {

            //Обьявили переменную присвоили ей значение функции 

           var decimalUtils = this.getDecimalUtils();

 



            // вернули значение переменой как функции в зависимости от переданных  параметров



            return decimalUtils.evaluate({multiply: [{divide: [percent, 100]}, amount]

            });

        },

**************************************************************************************

Зачем создали функцию getDecimalUtils и что в ней делают?

Зачем создали функции multiply и divide?

Далее смотрю эти функции getDecimalUtils, multiply и divide.

/**

         * Returns {@link Terrasoft.DecimalUtils} instance used to perform numeric computations.

         * @private

         * @return {Terrasoft.DecimalUtils}

         */

  

         

        getDecimalUtils: function(config) {

            config = config || {};

            if (!this.decimalUtils) {

                this.decimalUtils = Ext.create("Terrasoft.DecimalUtils");

            }

            this.decimalUtils.decimalPlaces = config.precision || Terrasoft.data.constants.MONEY_PRECISION;

            return this.decimalUtils;

        },

 

 

 

        /**

         * Divide x value by y value.

         * @param {Number} x Numerator.

         * @param {Number} y Denominator.

         * @return {Number} Returns result rounded to current number of decimal places.

         */

        divide: function(x, y) {

            return this.evaluate({divide: [x, y]});

        },

        /**

         * Multiplies x value by y value.

         * @param {Number} x Value.

         * @param {Number} y Value.

         * @return {Number} Returns result rounded to current number of decimal places.

         */

        multiply: function(x, y) {

            return this.evaluate({multiply: [x, y]});

        },



Зачем создали функцию evaluate которая в свою очередь использует функцию internalEvaluate ?

        /**

         * Evaluates operations provided in expression.

         * @param {Object} expression

         * Example:

         *    to compute expression ((totalAmount * discountTax) / (100 + discountTax)) used expression:

         *    {divide: [{multiply: [totalAmount, discountTax]}, {add: [100, discountTax]}]}

         *

         * @return {Number} Returns result rounded to current number of decimal places.

         */

        evaluate: function(expression) {

            var value = this.internalEvaluate(expression);

            return this.prepareValue(value);

        }

 

 



        /**

         * Evaluates passed expression.

         * @private

         * @param expression Expression to evaluate.

         * @param [operation] Expression operation (#operations).

         * @return {Object} decimal.js value, as result of evaluated expression.

         * @throw Terrasoft.InvalidFormatException if expression is incorrect.

         */

        internalEvaluate: function(expression, operation) {

            var resultItem = null;

            if (Ext.isNumber(expression)){

                resultItem = new this.decimal(expression);

            } else if (Ext.isObject(expression)) {

                Terrasoft.each(expression, function(item, operation) {

                    resultItem = this.internalEvaluate(item, operation);

                    return false;

                }, this);

            } else if (Ext.isArray(expression)) {

                if (!Ext.isDefined(operation)){

                    throw new Terrasoft.InvalidFormatException();

                }

                var resultArray = [];

                Terrasoft.each(expression, function(item, index) {

                    resultArray[index] = this.internalEvaluate(item);

                }, this);

                resultItem = this.applyOperation(operation, resultArray);

            }

            if (resultItem === null){

                return NaN;

            }

            return resultItem;

        },

Коллеги подскажите почему такая сложная реализация ?

Где можно просветится по такой методологии?

Почему не сделали   ??

amount = 10, percent = 20, result = 2 (2 is 20% of 10).

amount * percent  / 100  ( 10*20/100 ) = 2 

Спасибо, тем кто отзовется, если дадите ссылки на ресурсы почему так программируют буду признателен.

 

 

Нравится

2 комментария

Я так понял, что не используем просто формулу 

amount * percent  / 100  ( 10*20/100 ) = 2 

а пользуемся функцией getPercentagePart которая в свою очередь использует модуль DecimalUtils   (для избежания ошибок с плавающей точкой) . 

Коллеги разработчики террасофт дайте обратную связь я правильно понимаю необходимость такой реализации?

!!Далее пытаюсь понять код модуля DecimalUtils и его методов  Divide, Multiplies, evaluate, internalEvaluate, applyOperation !!!

как это позволило избежать ошибок округления?

 /**

         * Divide x value by y value.

         * @param {Number} x Numerator.

         * @param {Number} y Denominator.

         * @return {Number} Returns result rounded to current number of decimal places.

         */

        divide: function(x, y) {

            return this.evaluate({divide: [x, y]});

        },

        /**

         * Multiplies x value by y value.

         * @param {Number} x Value.

         * @param {Number} y Value.

         * @return {Number} Returns result rounded to current number of decimal places.

         */

        multiply: function(x, y) {

            return this.evaluate({multiply: [x, y]});

        },

Зачем создали функцию evaluate которая в свою очередь использует функцию internalEvaluate ?

        /**

         * Evaluates operations provided in expression.

         * @param {Object} expression

         * Example:

         *    to compute expression ((totalAmount * discountTax) / (100 + discountTax)) used expression:

         *    {divide: [{multiply: [totalAmount, discountTax]}, {add: [100, discountTax]}]}

         *

         * @return {Number} Returns result rounded to current number of decimal places.

         */

        evaluate: function(expression) {

            var value = this.internalEvaluate(expression);

            return this.prepareValue(value);

        }

        /**

         * Evaluates passed expression.

         * @private

         * @param expression Expression to evaluate.

         * @param [operation] Expression operation (#operations).

         * @return {Object} decimal.js value, as result of evaluated expression.

         * @throw Terrasoft.InvalidFormatException if expression is incorrect.

         */

        internalEvaluate: function(expression, operation) {

            var resultItem = null;

            if (Ext.isNumber(expression)){

                resultItem = new this.decimal(expression);

            } else if (Ext.isObject(expression)) {

                Terrasoft.each(expression, function(item, operation) {

                    resultItem = this.internalEvaluate(item, operation);

                    return false;

                }, this);

            } else if (Ext.isArray(expression)) {

                if (!Ext.isDefined(operation)){

                    throw new Terrasoft.InvalidFormatException();

                }

                var resultArray = [];

                Terrasoft.each(expression, function(item, index) {

                    resultArray[index] = this.internalEvaluate(item);

                }, this);

                resultItem = this.applyOperation(operation, resultArray);

            }

            if (resultItem === null){

                return NaN;

            }

            return resultItem;

        },

applyOperation

 

Такую «магию» действительно используют из-за странностей работы с плавающей запятой. Недавно в другой теме приводил ссылки на статьи.

Показать все комментарии