Angular.js 中的反向波兰符号计算器
A Reverse Polish Notation Calculator in Angular.js
我正在尝试在 Angular.js 中实现一个简单的 Revrse Polish Notation 计算器,到目前为止,代码可以处理一位数的计算,例如
2 3 +
如何修改它以处理多于一位的输入,例如:
122 233 +
这是我参加这个discussion后突然想到的想法。我怀疑我可能必须使用 onkeypress 和 parseInt and/or 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 = "";
};
});
您的第二个示例已经偏离了您的 (A B Operator)
语法。如果您打算保持一致以使解析更容易,它应该是
122 (233 41234 +) +
与任何编程语言一样,您需要开始做一些额外的解析工作,以解决不能再简单地按空格拆分的问题。如果你这样做了,你会得到
['122', '(233', '41234', '+)', '+']
解释如何解析您自己的领域特定语言 (DSL) 超出了此答案的范围。可以说您可能想要研究分词器以使工作更轻松。
最后,这种嵌套语法可以用递归来处理。这意味着您获取解析后的值并在 "tree" 中搜索分支。如果找到一个分支,就跟随它,如果它有一个分支,就跟随那个分支,等等。继续跟随分支,直到找到最深的节点。计算它们,然后 return 它们的值上升一个级别。继续以递归方式执行此操作,最终您将返回到最顶层,并从所有这些子计算中留下一个值。您 return 给用户的就是这个值。
就何时应执行此操作而言,您可以在用户每次单击按钮时执行此操作,或者仅在用户单击计算器上的 "calculate" 按钮时执行此操作。由你决定。
这真的比我预期的要容易得多,而且不需要 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>
解决方案取决于为操作数设置两个标志。最初它们是错误的。当用户点击 space 按钮时,具有讽刺意味的是它被设置为空字符串,左侧标志设置为 true 以表示左侧操作数的输入结束。右操作数的输入结束由用户单击操作符按钮标记。如果用户单击操作符而不是 "Sp" 按钮,该代码也是宽容的,在这种情况下,通过设置左标志来标记左操作数的输入结束。请注意,如果用户选择了错误的运算符,代码允许轻松选择不同的运算符。
我正在尝试在 Angular.js 中实现一个简单的 Revrse Polish Notation 计算器,到目前为止,代码可以处理一位数的计算,例如
2 3 +
如何修改它以处理多于一位的输入,例如:
122 233 +
这是我参加这个discussion后突然想到的想法。我怀疑我可能必须使用 onkeypress 和 parseInt and/or 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 = "";
};
});
您的第二个示例已经偏离了您的 (A B Operator)
语法。如果您打算保持一致以使解析更容易,它应该是
122 (233 41234 +) +
与任何编程语言一样,您需要开始做一些额外的解析工作,以解决不能再简单地按空格拆分的问题。如果你这样做了,你会得到
['122', '(233', '41234', '+)', '+']
解释如何解析您自己的领域特定语言 (DSL) 超出了此答案的范围。可以说您可能想要研究分词器以使工作更轻松。
最后,这种嵌套语法可以用递归来处理。这意味着您获取解析后的值并在 "tree" 中搜索分支。如果找到一个分支,就跟随它,如果它有一个分支,就跟随那个分支,等等。继续跟随分支,直到找到最深的节点。计算它们,然后 return 它们的值上升一个级别。继续以递归方式执行此操作,最终您将返回到最顶层,并从所有这些子计算中留下一个值。您 return 给用户的就是这个值。
就何时应执行此操作而言,您可以在用户每次单击按钮时执行此操作,或者仅在用户单击计算器上的 "calculate" 按钮时执行此操作。由你决定。
这真的比我预期的要容易得多,而且不需要 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>
解决方案取决于为操作数设置两个标志。最初它们是错误的。当用户点击 space 按钮时,具有讽刺意味的是它被设置为空字符串,左侧标志设置为 true 以表示左侧操作数的输入结束。右操作数的输入结束由用户单击操作符按钮标记。如果用户单击操作符而不是 "Sp" 按钮,该代码也是宽容的,在这种情况下,通过设置左标志来标记左操作数的输入结束。请注意,如果用户选择了错误的运算符,代码允许轻松选择不同的运算符。