Files
youlegames/codes/minipro/calculation/miniprogram/pages/calculator/calculator.ts

228 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// pages/calculator/calculator.ts
Page({
data: {
displayValue: '0',
history: '',
operator: null as string | null,
firstOperand: null as number | null,
waitingForSecondOperand: false,
isScientific: false
},
onLoad() {
},
vibrate() {
// wx.vibrateShort({ type: 'light' });
},
toggleMode() {
this.vibrate();
this.setData({
isScientific: !this.data.isScientific
});
},
onDigit(e: any) {
this.vibrate();
const digit = e.currentTarget.dataset.digit;
const { displayValue, waitingForSecondOperand } = this.data;
// 科学模式允许更多数字
const limit = 15;
if (!waitingForSecondOperand && displayValue.length >= limit) {
return;
}
if (waitingForSecondOperand) {
this.setData({
displayValue: digit,
waitingForSecondOperand: false
});
} else {
this.setData({
displayValue: displayValue === '0' ? digit : displayValue + digit
});
}
},
onDot() {
this.vibrate();
const { displayValue, waitingForSecondOperand } = this.data;
if (waitingForSecondOperand) {
this.setData({
displayValue: '0.',
waitingForSecondOperand: false
});
} else if (displayValue.indexOf('.') === -1) {
this.setData({
displayValue: displayValue + '.'
});
}
},
onClear() {
this.vibrate();
this.setData({
displayValue: '0',
history: '',
operator: null,
firstOperand: null,
waitingForSecondOperand: false
});
},
onDelete() {
this.vibrate();
const { displayValue } = this.data;
if (displayValue.length > 1) {
this.setData({
displayValue: displayValue.slice(0, -1)
});
} else {
this.setData({ displayValue: '0' });
}
},
onToggleSign() {
this.vibrate();
const { displayValue } = this.data;
const newValue = parseFloat(displayValue) * -1;
this.setData({
displayValue: String(newValue)
});
},
onConstant(e: any) {
this.vibrate();
const type = e.currentTarget.dataset.const;
let val = 0;
if (type === 'pi') val = Math.PI;
if (type === 'e') val = Math.E;
this.setData({
displayValue: String(val).slice(0, 10),
waitingForSecondOperand: true // 下次输入将开启新数字,或者作为操作数
});
},
onMathFunc(e: any) { // 单操作数立即计算
this.vibrate();
const func = e.currentTarget.dataset.func;
let val = parseFloat(this.data.displayValue);
let result = 0;
let desc = '';
switch(func) {
case 'sin':
// 默认转为弧度计算 (度数 * PI / 180)
result = Math.sin(val * Math.PI / 180);
desc = `sin(${val})`;
break;
case 'cos':
result = Math.cos(val * Math.PI / 180);
desc = `cos(${val})`;
break;
case 'tan':
result = Math.tan(val * Math.PI / 180);
desc = `tan(${val})`;
break;
case 'log':
result = Math.log10(val);
desc = `log(${val})`;
break;
case 'ln':
result = Math.log(val);
desc = `ln(${val})`;
break;
case 'sqrt':
result = Math.sqrt(val);
desc = `√(${val})`;
break;
case 'pow2':
result = Math.pow(val, 2);
desc = `sqr(${val})`;
break;
case 'percent':
result = val / 100;
desc = `${val}%`;
break;
}
// 格式化结果
const formatted = parseFloat(result.toPrecision(12));
this.setData({
displayValue: String(formatted),
history: desc,
waitingForSecondOperand: true // 计算完后,下次输入数字是新数字
});
},
onOperator(e: any) {
this.vibrate();
const nextOperator = e.currentTarget.dataset.op;
const { displayValue, operator, firstOperand } = this.data;
const inputValue = parseFloat(displayValue);
if (operator && this.data.waitingForSecondOperand) {
this.setData({
operator: nextOperator,
// 更新历史记录中的符号
history: `${firstOperand} ${nextOperator}`
});
return;
}
let newFirstOperand = firstOperand;
if (firstOperand == null) {
newFirstOperand = inputValue;
} else if (operator) {
const result = this.performCalculation(operator, firstOperand, inputValue);
newFirstOperand = result;
this.setData({
displayValue: String(result),
});
}
this.setData({
firstOperand: newFirstOperand,
waitingForSecondOperand: true,
operator: nextOperator,
history: `${newFirstOperand} ${nextOperator}`
});
},
onEqual() {
this.vibrate();
const { displayValue, operator, firstOperand } = this.data;
const inputValue = parseFloat(displayValue);
if (operator && firstOperand != null) {
const result = this.performCalculation(operator, firstOperand, inputValue);
this.setData({
displayValue: String(result),
firstOperand: null,
operator: null,
waitingForSecondOperand: true,
history: `${firstOperand} ${operator} ${inputValue} =`
});
}
},
performCalculation(op: string, first: number, second: number): number {
let result = 0;
switch(op) {
case '+': result = first + second; break;
case '-': result = first - second; break;
case '×': result = first * second; break;
case '÷': result = first / second; break;
default: return second;
}
const precision = 10000000000;
return Math.round(result * precision) / precision;
}
})