<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>科学计算器</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
padding: 20px;
}
.calculator {
background: #222;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7);
width: 100%;
max-width: 400px;
overflow: hidden;
}
.display {
background: #000;
padding: 25px 20px;
text-align: right;
position: relative;
}
.operation {
min-height: 25px;
color: #888;
font-size: 18px;
margin-bottom: 5px;
overflow-x: auto;
white-space: nowrap;
padding-bottom: 3px;
}
.result {
color: white;
font-size: 36px;
font-weight: 300;
overflow-x: auto;
white-space: nowrap;
}
.buttons {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 1px;
background: #444;
}
button {
border: none;
outline: none;
padding: 18px 5px;
font-size: 18px;
cursor: pointer;
transition: all 0.2s;
border-radius: 0;
}
/* 数字键 - 浅灰色 */
button.num {
background: #333;
color: white;
}
/* 基本运算符 - 蓝色 */
button.operator {
background: #0d6efd;
color: white;
font-weight: bold;
}
/* 科学函数 - 绿色 */
button.scientific {
background: #198754;
color: white;
font-size: 16px;
}
/* 特殊功能键 - 红色/橙色 */
button.special {
background: #dc3545;
color: white;
font-weight: bold;
}
/* 等号 - 橙色 */
button.equals {
background: #fd7e14;
color: white;
font-weight: bold;
grid-column: span 2;
}
button:hover {
opacity: 0.9;
transform: translateY(-2px);
}
button:active {
transform: translateY(0);
opacity: 0.8;
}
.header {
background: #333;
padding: 15px;
text-align: center;
color: white;
font-weight: bold;
font-size: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
@media (max-width: 420px) {
.calculator {
max-width: 100%;
}
button {
padding: 15px 5px;
font-size: 16px;
}
.result {
font-size: 32px;
}
}
</style>
</head>
<body>
<div class="calculator">
<div class="header">科学计算器</div>
<div class="display">
<div class="operation" id="operation"></div>
<div class="result" id="result">0</div>
</div>
<div class="buttons">
<!-- 第一行:科学函数 -->
<button class="scientific" onclick="addToOperation('sin(')">sin</button>
<button class="scientific" onclick="addToOperation('cos(')">cos</button>
<button class="scientific" onclick="addToOperation('tan(')">tan</button>
<button class="scientific" onclick="addToOperation('log(')">log</button>
<button class="scientific" onclick="addToOperation('ln(')">ln</button>
<!-- 第二行:科学函数 -->
<button class="scientific" onclick="addToOperation('asin(')">asin</button>
<button class="scientific" onclick="addToOperation('acos(')">acos</button>
<button class="scientific" onclick="addToOperation('atan(')">atan</button>
<button class="scientific" onclick="addToOperation('sqrt(')">√</button>
<button class="scientific" onclick="addToOperation('10^(')">10^x</button>
<!-- 第三行:科学函数和常量 -->
<button class="scientific" onclick="addToOperation('^')">x^y</button>
<button class="scientific" onclick="addToOperation('e^(')">e^x</button>
<button class="scientific" onclick="addToOperation('!')">x!</button>
<button class="scientific" onclick="addToOperation('π')">π</button>
<button class="scientific" onclick="addToOperation('e')">e</button>
<!-- 第四行:清除和符号 -->
<button class="special" onclick="clearEntry()">CE</button>
<button class="special" onclick="clearAll()">C</button>
<button class="special" onclick="backspace()">⌫</button>
<button class="operator" onclick="addToOperation('%')">%</button>
<button class="operator" onclick="addToOperation('/')">/</button>
<!-- 第五行:数字 -->
<button class="num" onclick="addToOperation('7')">7</button>
<button class="num" onclick="addToOperation('8')">8</button>
<button class="num" onclick="addToOperation('9')">9</button>
<button class="operator" onclick="addToOperation('*')">×</button>
<button class="scientific" onclick="addToOperation('(')">(</button>
<!-- 第六行:数字 -->
<button class="num" onclick="addToOperation('4')">4</button>
<button class="num" onclick="addToOperation('5')">5</button>
<button class="num" onclick="addToOperation('6')">6</button>
<button class="operator" onclick="addToOperation('-')">-</button>
<button class="scientific" onclick="addToOperation(')')">)</button>
<!-- 第七行:数字 -->
<button class="num" onclick="addToOperation('1')">1</button>
<button class="num" onclick="addToOperation('2')">2</button>
<button class="num" onclick="addToOperation('3')">3</button>
<button class="operator" onclick="addToOperation('+')">+</button>
<button class="scientific" onclick="toggleSign()">±</button>
<!-- 第八行:零和小数点 -->
<button class="num" onclick="addToOperation('0')" style="grid-column: span 2">0</button>
<button class="num" onclick="addToOperation('.')">.</button>
<button class="equals" onclick="calculate()">=</button>
</div>
</div>
<script>
let operation = '';
let result = '0';
const operationElement = document.getElementById('operation');
const resultElement = document.getElementById('result');
// 预定义常量
const constants = {
'π': Math.PI,
'e': Math.E
};
function updateDisplay() {
operationElement.textContent = operation;
resultElement.textContent = result;
}
function addToOperation(value) {
// 处理特殊符号
if (value === '!') {
if (operation && !isNaN(operation.slice(-1))) {
operation += value;
} else if (operation.endsWith(')')) {
// 在右括号后添加阶乘
operation += value;
}
updateDisplay();
return;
}
// 处理幂运算
if (value === '^') {
addToOperation('**');
return;
}
// 处理10^x
if (value === '10^(') {
addToOperation('10**(');
return;
}
// 处理e^x
if (value === 'e^(') {
addToOperation('Math.E**(');
return;
}
// 处理常量
if (constants[value] !== undefined) {
operation += constants[value];
updateDisplay();
return;
}
// 默认处理
if (result !== '0' || operation === '') {
operation += value;
result = '';
} else {
operation += value;
}
updateDisplay();
}
function clearAll() {
operation = '';
result = '0';
updateDisplay();
}
function clearEntry() {
if (operation !== '') {
operation = operation.slice(0, -1);
updateDisplay();
}
}
function backspace() {
if (operation.length > 0) {
operation = operation.substring(0, operation.length - 1);
updateDisplay();
}
}
function toggleSign() {
if (!operation) return;
// 查找最后一个数字的开始位置
let i = operation.length - 1;
while (i >= 0 && (/[0-9\.\-]/.test(operation[i]))) {
i--;
}
const lastNumberStr = operation.substring(i + 1);
// 如果已经是负数,移除负号
if (lastNumberStr.startsWith('-')) {
operation = operation.substring(0, i + 1) + lastNumberStr.substring(1);
}
// 如果是正数,在前面添加负号
else if (lastNumberStr !== '') {
operation = operation.substring(0, i + 1) + '-' + lastNumberStr;
}
// 如果是空,添加负号
else {
operation += '-';
}
updateDisplay();
}
// 安全计算阶乘
function safeFactorial(n) {
if (n < 0 || n % 1 !== 0) {
throw new Error("阶乘仅适用于非负整数");
}
if (n > 170) {
throw new Error("阶乘结果过大");
}
if (n === 0 || n === 1) return 1;
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}
// 解析并计算阶乘
function parseFactorials(expr) {
let result = '';
let i = 0;
while (i < expr.length) {
if (expr[i] === '!' && i > 0) {
// 查找前面的数字
let numStart = i - 1;
while (numStart >= 0 && (/[0-9\.]/.test(expr[numStart]))) {
numStart--;
}
numStart++;
const numStr = expr.substring(numStart, i);
const num = parseFloat(numStr);
if (!isNaN(num)) {
const fact = safeFactorial(num);
result = result.substring(0, numStart - (result.length - expr.length)) + fact;
i++;
continue;
}
}
result += expr[i];
i++;
}
return result;
}
// 解析幂运算
function parseExponents(expr) {
// 将所有 ^ 替换为 **,但保留函数调用中的 ^
let result = '';
let inFunction = 0;
let i = 0;
while (i < expr.length) {
if (expr[i] === '(') {
inFunction++;
} else if (expr[i] === ')') {
inFunction--;
} else if (expr[i] === '^' && inFunction === 0) {
result += '**';
i++;
continue;
}
result += expr[i];
i++;
}
return result;
}
function calculate() {
try {
// 保存原始操作以便显示
const originalOperation = operation;
// 检查括号是否匹配
let bracketCount = 0;
for (let char of operation) {
if (char === '(') bracketCount++;
if (char === ')') bracketCount--;
if (bracketCount < 0) break;
}
if (bracketCount !== 0) {
throw new Error("括号不匹配");
}
// 复制操作字符串用于处理
let expr = operation;
// 处理百分比 - 需要在其他处理之前
expr = expr.replace(/(\d+(\.\d+)?)%/g, function(match, p1) {
return '(' + p1 + '/100)';
});
// 处理阶乘
expr = parseFactorials(expr);
// 处理幂运算
expr = parseExponents(expr);
// 处理科学函数
expr = expr
.replace(/sin\(/g, 'Math.sin(')
.replace(/cos\(/g, 'Math.cos(')
.replace(/tan\(/g, 'Math.tan(')
.replace(/asin\(/g, 'Math.asin(')
.replace(/acos\(/g, 'Math.acos(')
.replace(/atan\(/g, 'Math.atan(')
.replace(/log\(/g, 'Math.log10(')
.replace(/ln\(/g, 'Math.log(')
.replace(/sqrt\(/g, 'Math.sqrt(');
// 特殊处理π和e
expr = expr.replace(/π/g, 'Math.PI').replace(/e/g, 'Math.E');
// 安全计算表达式
let calculatedResult;
try {
calculatedResult = Function('"use strict";return (' + expr + ')')();
} catch (e) {
throw new Error("表达式语法错误");
}
// 格式化结果
if (typeof calculatedResult === 'number') {
if (isNaN(calculatedResult)) {
throw new Error("结果未定义");
}
if (!isFinite(calculatedResult)) {
if (calculatedResult > 0) throw new Error("结果过大");
if (calculatedResult < 0) throw new Error("结果过小");
}
// 处理非常小的数
if (Math.abs(calculatedResult) < 1e-10) {
calculatedResult = 0;
}
// 处理非常大的数
else if (Math.abs(calculatedResult) > 1e15) {
calculatedResult = calculatedResult.toExponential(6);
}
// 保留适当的小数位数
else {
// 保留最多12位小数,但移除末尾多余的零
calculatedResult = parseFloat(calculatedResult.toFixed(12));
if (!Number.isInteger(calculatedResult)) {
calculatedResult = calculatedResult.toString().replace(/0+$/, '').replace(/\.$/, '');
}
}
}
result = calculatedResult.toString();
operation = originalOperation + ' =';
updateDisplay();
} catch (error) {
result = '错误: ' + error.message;
updateDisplay();
// 3秒后重置
setTimeout(() => {
if (result.startsWith('错误:')) {
clearAll();
}
}, 3000);
}
}
// 键盘支持
document.addEventListener('keydown', (event) => {
const key = event.key;
if (key >= '0' && key <= '9' || key === '.') {
addToOperation(key);
} else if (key === '+' || key === '-' || key === '*' || key === '/') {
addToOperation(key);
} else if (key === 'Enter' || key === '=') {
calculate();
} else if (key === 'Escape') {
clearAll();
} else if (key === 'Backspace') {
backspace();
} else if (key === '%') {
addToOperation('%');
} else if (key === '(' || key === ')') {
addToOperation(key);
}
});
// 初始化
updateDisplay();
</script>
</body>
</html>
index.html
index.html