Angular.js中的反向波兰表示计算器

时间:2017-06-10 23:16:17

标签: javascript angularjs calculator

我试图在Angular.js中实现一个简单的Revrse Polish Notation计算器,到目前为止代码可以处理像

这样的单位数计算
2 3 +

如何修改它以处理多个数字的输入,例如:

122 233 +

在参与此discussion之后,我想到了这个想法。我怀疑我可能必须使用 onkeypress parseInt 和/或 parseFloat ,但我不确定。我期待着你的想法。谢谢。

JavaScript的:

var calcApp = angular.module('calcApp', []);

calcApp.controller('calcCtrl', function ($scope) {

    $scope.leftOperand = "";
    $scope.operator = "";
    $scope.rightOperand = "";
    $scope.answer = "";


    $scope.setOperand = function (operandEntered) {
        ($scope.leftOperand)
        ? $scope.rightOperand += operandEntered + " "
        : $scope.leftOperand += operandEntered + " ";
 console.log($scope.leftOperand,$scope.rightOperand);
    };



    $scope.setOperator = function (operatorEntered) {
        $scope.operator = operatorEntered;
    };

    $scope.getAnswer = function () {
        var result = $scope.leftOperand + $scope.operator + $scope.rightOperand;
        var answer = eval(result);

        if (answer % 1 !== 0){   // % 1 to identify floats
            $scope.answer = answer.toFixed(2);
        }
        else {$scope.answer = answer;}

        $scope.leftOperand = $scope.answer;
        $scope.operator = "";
        $scope.rightOperand = "";
    };

    $scope.setClear = function (a) {
          $scope.leftOperand = "";
          $scope.operator = "";
          $scope.rightOperand = "";
          $scope.answer = "";

    };


});

2 个答案:

答案 0 :(得分:3)

您的第二个示例已经偏离了(A B Operator)语法。如果您计划保持一致性以使解析更容易,那么应该

122 (233 41234 +) +

与任何编程语言一样,您需要开始做一些额外的解析工作,以解决您不能再简单地拆分空间的事实。如果你这样做了,你最终会用

['122', '(233', '41234', '+)', '+']

解释如何解析自己的特定于域的语言(DSL)超出了本答案的范围。我只想说你可能想要使用标记器来简化工作。

最后,可以使用递归来处理这种类型的嵌套语法。这意味着您将获取已解析的值并在“树”中搜索分支。如果您找到分支,请按照它,如果它有分支,请遵循该分支等。继续跟随分支,直到找到最深的节点。计算它们,然后将它们的值返回一个级别。继续以递归方式执行此操作,最终您将返回到最顶层,并从所有这些子计算中留下一个值。这是您返回给用户的值。

就何时应该执行此操作而言,您可以在每次用户单击按钮时执行此操作,或者仅在他们单击计算器上的“计算”按钮时执行此操作。这取决于你。

答案 1 :(得分:0)

这比我预期的要容易得多,并且不需要onkeypress,ParseInt或ParseFloat。这是最终起作用的:

var calcApp = angular.module("calcApp", []);

calcApp.controller("calcCtrl", function($scope) {
  $scope.leftOperand = "";
  $scope.operator = "";
  $scope.rightOperand = "";
  $scope.answer = "";

  var left = false; // flags
  var right = false;

  $scope.setOperand = function(operandEntered) {
    if (left == false && operandEntered >= 0 && operandEntered <= 9) {
      $scope.leftOperand += operandEntered;
      if (operandEntered == "") {
        left = true;
      }
    } else if (right == false) {
      $scope.rightOperand += operandEntered;
    }
  };

  $scope.setOperator = function(operatorEntered) {
    if (left == true && $scope.rightOperand) {
      $scope.operator = operatorEntered;
      right = true;
    }
    else if($scope.rightOperand=="")
    {
        left = true; // end of leftOperand input
    }
  };

  $scope.getAnswer = function() {
    var result = $scope.leftOperand + $scope.operator + $scope.rightOperand;
    var answer = eval(result);

    if (answer % 1 !== 0) {
      // % 1 to identify floats
      $scope.answer = answer.toFixed(2);
    } else {
      $scope.answer = answer;
    }

    $scope.leftOperand = $scope.answer;
    $scope.operator = "";
    $scope.rightOperand = "";
  };

  $scope.setClear = function() {
    $scope.leftOperand = "";
    $scope.operator = "";
    $scope.rightOperand = "";
    $scope.answer = "";
    left = false;
    right = false;
  };
});
#answerScreen {
  background-color: lightgray;
  border: 3px inset white;
  font: 23px Arial, Helvetica;
  font-weight: bold;
  height: 34px;
  padding-left: 3px;
  width: 215px;
}

button {
  border-radius: 10px;
  border-color: pink;
  font-weight: bold;
  height: 2em;
  width: 2em;
}

#rpn {
  text-align: center;
}

.calcButtonsrow {
  padding: 4px;
}

#calcButtonsBox {
  border-style: groove;
}

#clear {
  background-color: #FFAAAA;
}

body {
  padding-top: 7vh;
}

#space {
  background-color: #cff;
  text-align: center;
  padding: 0;
}

.overflow-hidden {
  overflow: hidden;
}

#plusSign,
#multiplySign,
#minusSign,
#divideBySign {
  border-radius: 10px;
  font-weight: bold;
  height: 2em;
  width: 2em;
}

#plusSign:hover,
#multiplySign:hover,
#minusSign:hover,
#equalSign:hover,
#divideBySign:hover {
  background-color: #ff9;
  color: black;
}

#equalSign {
  color: #FA6800;
}

#modalCalcButt {
  height: 150px !important;
  width: 150px !important;
}

#OpenSource {
  font-weight: bold;
}
<html lang="en-us" ng-app="calcApp" class="full-height">

<head>
  <title></title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>


<body>
  <div class="theCalculator" ng-controller="calcCtrl">
    <div class="calcButtonsrow" id="1stLine">
      <div id="answerScreen">
        <span>{{leftOperand}}</span>
        <span>{{rightOperand}}</span>
        <span>{{operator}}</span>
        <span>{{clear}}</span>
      </div>
    </div>
    <div><span>RPN Calculator - Usage: </span><span id="OpenSource">Number(s) {Sp} Number(s) {operator} {=}</span></div>
    <div class="calcButtonsrow" id="2ndLine">
      <button class="number" id="7" ng-click="setOperand('7')">7</button>
      <button class="number" id="8" ng-click="setOperand('8')">8</button>
      <button class="number" id="9" ng-click="setOperand('9')">9</button>
      <button id="divideBySign" ng-click="setOperator('/')" class=" operator">/</button>
    </div>
    <div class="calcButtonsrow" id="3rdLine">
      <button class="number" id="4" ng-click="setOperand('4')">4</button>
      <button class="number" id="5" ng-click="setOperand('5')">5</button>
      <button class="number" id="6" ng-click="setOperand('6')">6</button>
      <button id="multiplySign" ng-click="setOperator('*')" class=" operator">*</button>
    </div>
    <div class="calcButtonsrow" id="4thLine">
      <button class="number" id="1" ng-click="setOperand('1')">1</button>
      <button class="number" id="2" ng-click="setOperand('2')">2</button>
      <button class="number" id="3" ng-click="setOperand('3')">3</button>
      <button id="minusSign" ng-click="setOperator('-')" class=" operator">-</button>

    </div>
    <div class="calcButtonsrow" id="5thLine">
      <button id="clear" ng-click="setClear('C')">C</button>
      <button class="number" id="0" ng-click="setOperand('0')">0</button>
      <button id="equalSign" ng-click="getAnswer('=')" ng-disabled="!leftOperand || !rightOperand || !operator">=</button>
      <button id="plusSign" ng-click="setOperator('+')" class="operator">+</button>
      <button id="space" ng-click="setOperand('')" class="operator">Sp</button>
    </div>
  </div>


  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
  </script>

</body>

</html>

解决方案取决于为操作数设置两个标志。最初他们是假的。在用户敲击具有讽刺意味的空字符串的空格按钮时,左标志被设置为真以指示左操作数的输入结束。右操作数的输入结束由用户单击操作员按钮标记。如果用户单击操作符而不是“Sp”按钮,代码也是宽容的,在这种情况下,左操作数的输入结束通过设置左标志来标记。请注意,如果用户选择了错误的操作符,则代码允许轻松选择不同的操作符。