/**! * * Copyright(c) boyce and other contributors. * MIT Licensed * * Authors: * boyce (http://www.jianshu.com/users/9b5b907d9bce) */ 'use strict' const STATE = { INIT: 0, //初始状态 RESULT: 1, //结果状态 FIRST_UNDOT: 2, //记录第一个操作数,且该操作数没有小数点 FIRST_DOT: 3, //记录第一个操作数,且该操作数有小数点 SECOND_UNDOT: 4, //记录第二个操作数,且该操作数没有小数点 SECOND_DOT: 5 //记录第二个操作数,且该操作数有小数点 } let curState = STATE.INIT //状态机所在状态 let curResult = 0 //计算结果 let opNum1 = '0' //操作数1 let opNum2 = '' //操作数2 let op = '' //操作符 let displayNum = opNum1 //界面上应当显示的数值 let displayOp = "" //界面上应当显示的操作符 /** * 重置程序状态 */ function reset() { curState = STATE.INIT curResult = 0 opNum1 = '0' opNum2 = '' op = '' } /** * 是否为零 */ function isZero(code) { return code == '0' } /** * 是否数字 */ function isNumber(code) { return code >= '0' && code <= '9' } /** * 是否操作符 */ function isOperator(code) { return code == '+' || code == '-' || code == 'x' || code == '/' || code == '%' } /** * 是否小数点 */ function isDot(code) { return code == '.' } /** * 是否是等号 */ function isEquel(code) { return code == '=' } /** * 是否清楚 */ function isClear(code) { return code == 'c' } /** * 是否删除 */ function isDelete(code) { return code == 'd' } /** * 转换为可现实的操作符 */ function op2Show(code) { return code == '/' ? '÷' : (code == 'x' ? '×' : code) } /** * */ function tryAppend(num, code) { if (num.length < 15) { num += code } return num } function tryTrunc(num) { let str = '' + num if (str.length > 15) { str = str.substr(0, 15) } return str } /** * */ function tryDelete() { if (curState == STATE.SECOND_DOT || curState == STATE.SECOND_UNDOT) { if (opNum2.length > 0) { opNum2 = opNum2.substr(0, opNum2.length - 1) } if (opNum2 == '') { opNum2 = '0' } return } else { if (opNum1.length > 0 && opNum1 != '0') { opNum1 = opNum1.substr(0, opNum1.length - 1) } if (opNum1 == '') { opNum1 = '0' } return } } function tryCalc() { let n1 = parseFloat(opNum1) let n2 = parseFloat(opNum2) switch (op) { case '+': curResult = n1 + n2 break case '-': curResult = n1 - n2 break case 'x': curResult = n1 * n2 break case '/': if (n2 == 0) { reset() curResult = 'NaN' displayOp = '' } else { curResult = n1 / n2 } break case '%': if (n2 == 0) { reset() curResult = 'NaN' displayOp = '' } else { curResult = n1 % n2 } break } curResult = tryTrunc(curResult) } function addOp(code) { switch (curState) { case STATE.RESULT: case STATE.INIT: if (isNumber(code) && !isZero(code)) { curState = STATE.FIRST_UNDOT opNum1 = code } else if (isDot(code)) { curState = STATE.FIRST_DOT opNum1 = '0.' } else if (isOperator(code)) { curState = STATE.SECOND_UNDOT opNum1 = '0' opNum2 = '' op = code } displayNum = opNum1 displayOp = '' break case STATE.FIRST_UNDOT: displayOp = '' if (isNumber(code)) { if (!isZero(opNum1)) { opNum1 = tryAppend(opNum1, code) } else { opNum1 = code } } else if (isDot(code)) { curState = STATE.FIRST_DOT opNum1 = opNum1 == '' ? '0' : tryAppend(opNum1, '.') } else if (isDelete(code)) { tryDelete() } else if (isOperator(code)) { curState = STATE.SECOND_UNDOT op = code opNum2 = '' displayOp = op } displayNum = opNum1 break case STATE.FIRST_DOT: displayOp = '' if (isNumber(code)) { opNum1 = tryAppend(opNum1, code) } else if (isDelete(code)) { tryDelete() if (opNum1.indexOf('.') < 0) curState = STATE.FIRST_UNDOT } else if (isOperator(code)) { curState = STATE.SECOND_UNDOT op = code opNum2 = '' displayOp = op } displayNum = opNum1 break case STATE.SECOND_UNDOT: if (isNumber(code)) { if (!isZero(opNum2)) { opNum2 = tryAppend(opNum2, code) } else { opNum2 = code } displayNum = opNum2 } else if (isDot(code)) { curState = STATE.SECOND_DOT opNum2 = opNum2 == '' ? '0' : tryAppend(opNum2, '.') displayNum = opNum2 } else if (isDelete(code)) { tryDelete() displayNum = opNum2 } else if (isOperator(code)) { if (opNum2 != '') { //直接计算 tryCalc() curState = STATE.SECOND_UNDOT opNum1 = curResult opNum2 = '' displayNum = curResult } op = code displayOp = op } else if (isEquel(code)) { if (opNum2 != '') { tryCalc() curState = STATE.RESULT opNum1 = '0' opNum2 = '' displayNum = curResult } op = code displayOp = op } break case STATE.SECOND_DOT: if (isNumber(code)) { opNum2 = tryAppend(opNum2, code) displayNum = opNum2 } else if (isDelete(code)) { tryDelete() if (opNum2.indexOf('.') < 0) curState = STATE.SECOND_UNDOT displayNum = opNum2 } else if (isOperator(code)) { if (opNum2 != '') { //直接计算 tryCalc() curState = STATE.SECOND_UNDOT opNum1 = curResult opNum2 = '' displayNum = curResult } op = code displayOp = op } else if (isEquel(code)) { if (opNum2 != '') { tryCalc() curState = STATE.RESULT opNum1 = '0' opNum2 = '' displayNum = curResult } op = code displayOp = op } break } if (isClear(code)) { reset() displayNum = opNum1 displayOp = '' } displayOp = op2Show(displayOp) } reset() module.exports = { reset, addOp, getVars(){ return {curState, curResult, opNum1, opNum2, op, displayNum, displayOp} } }