使用闭包计算多个函数调用的平均值

Calculating the average of several function invocations using closures

我正在做一个编码挑战,内容如下:

创建一个函数 runningAverage() returns 一个可调用的函数对象。用每个给定值更新系列并计算当前平均值。

rAvg = runningAverage();
rAvg(10) = 10.0;
rAvg(11) = 10.5;
rAvg(12) = 11;

我有一个可行的解决方案,但他们也希望结果像这样四舍五入:

rAvg(13) = 13.50678; => 13.50
rAvg(13) = 13.50; => 13.50
rAvg(13) = 13.5; => 13.5
rAvg(13) = 13; => 13

这是我的代码:



function runningAverage() {

  let number = 0;
  let numbOfFunctionCalls = 0;
  
  return function (y) {

    number += y;
    numbOfFunctionCalls ++;
    let average = (number/numbOfFunctionCalls);
    let averageArray = average.toString().split('.');

    //to get the number of decimal places
    //e.g 11.543 ==> ['11', '543']
    if ((Array.from(averageArray[1]).length) >= 2) {
      return average.toPrecision(2);
    }

    else if ((Array.from(averageArray[1]).length) = 1) {
      return average.toPrecision(1);
    }

    else {
      return average;
    }
  
  }
}

我分别测试了部分函数,​​它似乎可以工作,但当我调用它时,我收到消息 'cannot convert undefined or null to object'。

不确定这是否有效,但请尝试一下

function runningAverage() {
    let number = 0;
    let numbOfFunctionCalls = 0;
    
    return function (y) {
        number += y;
        numbOfFunctionCalls ++;

        let average = (number/numbOfFunctionCalls);
        let averageArray = average.toString().split('.');
    
        if ((Array.from(averageArray[1]).length) >= 2) {
            return Math.round(average.toPrecision(2) * 2) / 2;
        } else if ((Array.from(averageArray[1]).length) == 1) {
            return Math.round(average.toPrecision(1) * 2) / 2;
        } else {
            return Math.round(average * 2) / 2;
        };
    };
};

这听起来像是一个有趣的编码挑战!

  1. 在这种情况下,您需要 toFixed(),而不是 toPrecision()toPrecision() 本质上允许您确定 TOTAL 应出现的位数(包括小数点左侧的位数),而 toFixed() 侧重于 [=28= 的位数]右的小数点。请随意在 MDN 上查找这两种方法。当你读到 toPrecision() 可能 return 指数表示法时,这应该让你停下来思考,“这很奇怪。为什么会这样?什么时候会这样?”,而不是“这个细节不重要。 “

  2. 您的 .length = 1 比较需要修改为 ===.

  3. 如果整数是提供给 rAvg() 的第一个数字,您的代码当前将失败。在您的第一个条件中,Array.from(undefined) 可能 运行,这在 JavaScript 中是不允许的。您应该考虑仅在“小数点右侧有数字”的情况下才使用“小数点右侧的数字”的方法。

这是一个包含所有建议的有效解决方案,以防有人感兴趣:

function runningAverage() {

  let number = 0;
  let numbOfFunctionCalls = 0;
  
  return function (y) {

    number += y;
    numbOfFunctionCalls ++;
    let average = (number/numbOfFunctionCalls);
    let numIsDecimal = average.toString().includes('.');


    if (numIsDecimal) {
      
    let averageArray = average.toString().split('.');

    //to get the number of decimal places
    //e.g 11.543 ==> ['11', '543']
    if ((Array.from(averageArray[1]).length) >= 2) {
      return Number(average.toFixed(2));
    }
  
    if ((Array.from(averageArray[1]).length) === 1) {
      return Number(average.toFixed(1));
    }

    }

    else {
      return Number(average);
    }
  
  }
}