init geek calc
Some checks failed
Deploy to GitHub Pages / build-and-deploy (push) Has been cancelled
Some checks failed
Deploy to GitHub Pages / build-and-deploy (push) Has been cancelled
This commit is contained in:
141
rpn-calculator.js
Normal file
141
rpn-calculator.js
Normal file
@@ -0,0 +1,141 @@
|
||||
// RPN (Reverse Polish Notation) calculator module
|
||||
const RPNCalculator = (function() {
|
||||
class RPNCalculator {
|
||||
constructor() {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
// Push a number onto the stack
|
||||
push(value) {
|
||||
if (typeof value === 'number' || !isNaN(parseFloat(value))) {
|
||||
this.stack.push(parseFloat(value));
|
||||
}
|
||||
}
|
||||
|
||||
// Pop a number from the stack
|
||||
pop() {
|
||||
if (this.stack.length > 0) {
|
||||
return this.stack.pop();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Perform an operation on stack values
|
||||
operate(operator) {
|
||||
if (this.stack.length < 2) {
|
||||
return 'Error'; // Need at least 2 values for binary operations
|
||||
}
|
||||
|
||||
const b = this.pop();
|
||||
const a = this.pop();
|
||||
let result;
|
||||
|
||||
switch (operator) {
|
||||
case '+':
|
||||
result = a + b;
|
||||
break;
|
||||
case '-':
|
||||
result = a - b;
|
||||
break;
|
||||
case '*':
|
||||
result = a * b;
|
||||
break;
|
||||
case '/':
|
||||
if (b === 0) {
|
||||
result = Infinity;
|
||||
} else {
|
||||
result = a / b;
|
||||
}
|
||||
break;
|
||||
case '^':
|
||||
case '**':
|
||||
result = Math.pow(a, b);
|
||||
break;
|
||||
default:
|
||||
return 'Error'; // Unknown operator
|
||||
}
|
||||
|
||||
// Check for invalid results
|
||||
if (isNaN(result) || !isFinite(result)) {
|
||||
this.push('Error');
|
||||
return 'Error';
|
||||
}
|
||||
|
||||
this.push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clear the entire stack
|
||||
clear() {
|
||||
this.stack = [];
|
||||
}
|
||||
|
||||
// Get current stack state
|
||||
getStack() {
|
||||
return [...this.stack]; // Return a copy to prevent external modification
|
||||
}
|
||||
|
||||
// Execute RPN expression (e.g., "3 4 +")
|
||||
evaluate(rpnExpression) {
|
||||
try {
|
||||
// Split the expression into tokens
|
||||
const tokens = rpnExpression.trim().split(/\s+/);
|
||||
|
||||
this.clear(); // Clear the stack before evaluation
|
||||
|
||||
for (const token of tokens) {
|
||||
if (['+', '-', '*', '/', '^', '**'].includes(token)) {
|
||||
// It's an operator
|
||||
const result = this.operate(token);
|
||||
if (result === 'Error') {
|
||||
return 'Error';
|
||||
}
|
||||
} else {
|
||||
// It's a number
|
||||
const num = parseFloat(token);
|
||||
if (isNaN(num)) {
|
||||
return 'Error'; // Invalid token
|
||||
}
|
||||
this.push(num);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the top of the stack if there's a result
|
||||
if (this.stack.length === 1) {
|
||||
return this.stack[0];
|
||||
} else if (this.stack.length === 0) {
|
||||
return 0; // Empty stack, return 0
|
||||
} else {
|
||||
return this.stack[this.stack.length - 1]; // Return top of stack
|
||||
}
|
||||
} catch (error) {
|
||||
return 'Error';
|
||||
}
|
||||
}
|
||||
|
||||
// Process a single RPN input token
|
||||
processInput(token) {
|
||||
if (['+', '-', '*', '/', '^', '**'].includes(token)) {
|
||||
// Operator
|
||||
return this.operate(token);
|
||||
} else if (token === 'ENTER' || token === 'E') {
|
||||
// ENTER doesn't do anything in implementation, just pushes numbers that were already processed
|
||||
return this.getStack();
|
||||
} else if (token === 'C' || token === 'CE') {
|
||||
this.clear();
|
||||
return 0;
|
||||
} else {
|
||||
// Number
|
||||
const num = parseFloat(token);
|
||||
if (!isNaN(num)) {
|
||||
this.push(num);
|
||||
return num;
|
||||
} else {
|
||||
return 'Error';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { RPNCalculator };
|
||||
})();
|
||||
Reference in New Issue
Block a user