科学计算器edit icon

作者:
邓朝元
Fork(复制)
下载
嵌入
BUG反馈
index.html
现在支持上传本地图片了!
index.html
            
            <!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>
        
编辑器加载中
预览
控制台