<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>简易计算器</title>
<style>
* {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
user-select: none;
}
body {
margin: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #1c1f26;
font-family: 'Segoe UI', Roboto, sans-serif;
padding: 12px;
}
.calculator {
width: 100%;
max-width: 400px;
background: #2d323c;
border-radius: 24px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.display {
background: #1e2229;
border-radius: 16px;
padding: 20px 16px;
margin-bottom: 16px;
min-height: 100px;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
overflow: hidden;
}
.expression {
font-size: 18px;
color: #8a93a3;
word-break: break-all;
text-align: right;
min-height: 24px;
max-height: 48px;
overflow-y: auto;
width: 100%;
}
.result {
font-size: 40px;
color: #ffffff;
font-weight: 600;
word-break: break-all;
text-align: right;
width: 100%;
line-height: 1.2;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.btn {
height: 64px;
border: none;
border-radius: 16px;
font-size: 24px;
font-weight: 500;
background: #3a4150;
color: #e8ecf1;
cursor: pointer;
transition: filter 0.1s, transform 0.05s;
display: flex;
align-items: center;
justify-content: center;
}
.btn:active {
filter: brightness(1.4);
transform: scale(0.95);
}
.btn.function {
background: #4c5568;
color: #ffb74d;
}
.btn.operator {
background: #ff9d2e;
color: #1c1f26;
font-size: 28px;
}
.btn.equals {
background: #ff9d2e;
color: #1c1f26;
grid-column: span 1;
}
.btn.zero {
grid-column: span 2;
}
.btn.clear {
background: #e05a5a;
color: white;
}
.btn.backspace {
background: #4c5568;
color: #ffb74d;
}
</style>
</head>
<body>
<div class="calculator">
<div class="display">
<div class="expression" id="expression"></div>
<div class="result" id="result">0</div>
</div>
<div class="buttons">
<button class="btn clear" onclick="clearAll()">AC</button>
<button class="btn backspace" onclick="backspace()">⌫</button>
<button class="btn function" onclick="addOperator('%')">%</button>
<button class="btn operator" onclick="addOperator('/')">÷</button>
<button class="btn" onclick="addNumber('7')">7</button>
<button class="btn" onclick="addNumber('8')">8</button>
<button class="btn" onclick="addNumber('9')">9</button>
<button class="btn operator" onclick="addOperator('*')">×</button>
<button class="btn" onclick="addNumber('4')">4</button>
<button class="btn" onclick="addNumber('5')">5</button>
<button class="btn" onclick="addNumber('6')">6</button>
<button class="btn operator" onclick="addOperator('-')">−</button>
<button class="btn" onclick="addNumber('1')">1</button>
<button class="btn" onclick="addNumber('2')">2</button>
<button class="btn" onclick="addNumber('3')">3</button>
<button class="btn operator" onclick="addOperator('+')">+</button>
<button class="btn zero" onclick="addNumber('0')">0</button>
<button class="btn" onclick="addDot()">.</button>
<button class="btn equals" onclick="calculate()">=</button>
</div>
</div>
<script>
let currentExpression = '';
let lastResult = null;
let justEvaluated = false;
const expressionEl = document.getElementById('expression');
const resultEl = document.getElementById('result');
function updateDisplay() {
expressionEl.textContent = currentExpression;
if (currentExpression === '') {
resultEl.textContent = '0';
} else {
try {
const val = Function('"use strict"; return (' + currentExpression + ')')();
if (typeof val === 'number' && isFinite(val)) {
resultEl.textContent = parseFloat(val.toPrecision(12)).toString();
} else {
resultEl.textContent = 'Error';
}
} catch (e) {
// 不完整表达式,显示当前输入或0
const lastChar = currentExpression[currentExpression.length - 1];
if (lastChar && '+-*/%'.includes(lastChar)) {
resultEl.textContent = '';
} else {
resultEl.textContent = currentExpression || '0';
}
}
}
}
function addNumber(num) {
if (justEvaluated) {
currentExpression = '';
justEvaluated = false;
}
currentExpression += num;
updateDisplay();
}
function addOperator(op) {
if (justEvaluated) {
// 在结果后继续运算
justEvaluated = false;
}
if (currentExpression === '' && lastResult !== null && !justEvaluated) {
currentExpression = lastResult.toString();
}
const lastChar = currentExpression[currentExpression.length - 1];
if (lastChar && '+-*/%'.includes(lastChar)) {
// 替换最后一个运算符
currentExpression = currentExpression.slice(0, -1) + op;
} else if (currentExpression !== '') {
currentExpression += op;
} else {
// 空表达式不允许运算符开头(除非负号)
if (op === '-') {
currentExpression = '-';
} else {
return;
}
}
updateDisplay();
}
function addDot() {
if (justEvaluated) {
currentExpression = '';
justEvaluated = false;
}
// 检查当前数字是否已有小数点
const parts = currentExpression.split(/[+\-*/%]/);
const lastPart = parts[parts.length - 1];
if (lastPart.includes('.')) {
return;
}
if (currentExpression === '' || /[+\-*/%]/.test(currentExpression[currentExpression.length - 1])) {
currentExpression += '0.';
} else {
currentExpression += '.';
}
updateDisplay();
}
function calculate() {
if (currentExpression === '') return;
try {
let expr = currentExpression;
// 将%转换为 /100 处理
expr = expr.replace(/%/g, '/100');
// 将× ÷ 转为 * /
expr = expr.replace(/×/g, '*').replace(/÷/g, '/');
let val = Function('"use strict"; return (' + expr + ')')();
if (typeof val !== 'number' || !isFinite(val)) {
resultEl.textContent = 'Error';
expressionEl.textContent = currentExpression;
return;
}
val = parseFloat(val.toPrecision(12));
lastResult = val;
expressionEl.textContent = currentExpression + ' =';
resultEl.textContent = val.toString();
currentExpression = '';
justEvaluated = true;
} catch (e) {
resultEl.textContent = 'Error';
expressionEl.textContent = currentExpression;
justEvaluated = false;
}
}
function clearAll() {
currentExpression = '';
lastResult = null;
justEvaluated = false;
updateDisplay();
}
function backspace() {
if (justEvaluated) {
currentExpression = lastResult !== null ? lastResult.toString() : '';
justEvaluated = false;
return;
}
currentExpression = currentExpression.slice(0, -1);
updateDisplay();
}
// 键盘支持
document.addEventListener('keydown', function(e) {
const key = e.key;
if (/[0-9]/.test(key)) {
addNumber(key);
} else if (key === '+' || key === '-' || key === '*' || key === '/') {
addOperator(key);
} else if (key === '.') {
addDot();
} else if (key === 'Enter' || key === '=') {
e.preventDefault();
calculate();
} else if (key === 'Backspace') {
backspace();
} else if (key === 'Escape' || key.toLowerCase() === 'c') {
clearAll();
}
});
</script>
</body>
</html>