|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Professional Scientific Calculator</title> |
|
<script src="https://cdn.tailwindcss.com"></script> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
<style> |
|
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300;400;500;700&display=swap'); |
|
|
|
body { |
|
font-family: 'Roboto Mono', monospace; |
|
} |
|
|
|
.calculator { |
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.display { |
|
min-height: 120px; |
|
word-break: break-all; |
|
} |
|
|
|
.btn { |
|
transition: all 0.1s ease; |
|
transform-origin: center; |
|
} |
|
|
|
.btn:active { |
|
transform: scale(0.95); |
|
} |
|
|
|
.btn-operator { |
|
background-color: #3b82f6; |
|
color: white; |
|
} |
|
|
|
.btn-operator:hover { |
|
background-color: #2563eb; |
|
} |
|
|
|
.btn-function { |
|
background-color: #10b981; |
|
color: white; |
|
} |
|
|
|
.btn-function:hover { |
|
background-color: #059669; |
|
} |
|
|
|
.btn-equals { |
|
background-color: #f59e0b; |
|
color: white; |
|
} |
|
|
|
.btn-equals:hover { |
|
background-color: #d97706; |
|
} |
|
|
|
.btn-clear { |
|
background-color: #ef4444; |
|
color: white; |
|
} |
|
|
|
.btn-clear:hover { |
|
background-color: #dc2626; |
|
} |
|
|
|
.btn-secondary { |
|
background-color: #4b5563; |
|
color: white; |
|
} |
|
|
|
.btn-secondary:hover { |
|
background-color: #374151; |
|
} |
|
|
|
.btn-number { |
|
background-color: #1f2937; |
|
color: white; |
|
} |
|
|
|
.btn-number:hover { |
|
background-color: #111827; |
|
} |
|
|
|
.history-item:hover { |
|
background-color: #f3f4f6; |
|
cursor: pointer; |
|
} |
|
|
|
.tab-active { |
|
border-bottom: 3px solid #3b82f6; |
|
font-weight: 500; |
|
} |
|
|
|
.scientific-panel { |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.angle-unit { |
|
background-color: #e5e7eb; |
|
color: #1f2937; |
|
} |
|
|
|
.angle-unit.active { |
|
background-color: #3b82f6; |
|
color: white; |
|
} |
|
</style> |
|
</head> |
|
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-4"> |
|
<div class="calculator w-full max-w-md bg-white rounded-2xl overflow-hidden shadow-xl"> |
|
|
|
<div class="flex border-b"> |
|
<div class="tab tab-active py-3 px-6 text-center flex-1 cursor-pointer" data-tab="basic"> |
|
<i class="fas fa-calculator mr-2"></i> Basic |
|
</div> |
|
<div class="tab py-3 px-6 text-center flex-1 cursor-pointer" data-tab="scientific"> |
|
<i class="fas fa-square-root-alt mr-2"></i> Scientific |
|
</div> |
|
<div class="tab py-3 px-6 text-center flex-1 cursor-pointer" data-tab="history"> |
|
<i class="fas fa-history mr-2"></i> History |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="display p-4 bg-gray-50 text-right"> |
|
<div id="expression" class="text-gray-500 text-lg min-h-6 overflow-x-auto whitespace-nowrap"></div> |
|
<div id="result" class="text-3xl font-semibold mt-2 overflow-x-auto whitespace-nowrap">0</div> |
|
</div> |
|
|
|
|
|
<div class="scientific-panel hidden px-4 py-2 bg-gray-100 flex justify-center space-x-2"> |
|
<button class="angle-unit active px-3 py-1 rounded-full text-sm" data-unit="deg">DEG</button> |
|
<button class="angle-unit px-3 py-1 rounded-full text-sm" data-unit="rad">RAD</button> |
|
<button class="angle-unit px-3 py-1 rounded-full text-sm" data-unit="grad">GRAD</button> |
|
</div> |
|
|
|
|
|
<div class="grid grid-cols-5 gap-1 p-2"> |
|
|
|
<button class="btn btn-clear col-span-2 py-4 rounded" data-action="clear">AC</button> |
|
<button class="btn btn-clear py-4 rounded" data-action="backspace"> |
|
<i class="fas fa-backspace"></i> |
|
</button> |
|
<button class="btn btn-secondary py-4 rounded" data-action="percentage">%</button> |
|
<button class="btn btn-operator py-4 rounded" data-action="divide">÷</button> |
|
|
|
|
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="sin">sin</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="cos">cos</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="tan">tan</button> |
|
<button class="btn btn-secondary py-4 rounded" data-action="power">x^y</button> |
|
<button class="btn btn-operator py-4 rounded" data-action="multiply">×</button> |
|
|
|
|
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="asin">sin⁻¹</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="acos">cos⁻¹</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="atan">tan⁻¹</button> |
|
<button class="btn btn-secondary py-4 rounded" data-action="square">x²</button> |
|
<button class="btn btn-operator py-4 rounded" data-action="subtract">−</button> |
|
|
|
|
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="log">log</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="ln">ln</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="factorial">x!</button> |
|
<button class="btn btn-secondary py-4 rounded" data-action="sqrt">√</button> |
|
<button class="btn btn-operator py-4 rounded" data-action="add">+</button> |
|
|
|
|
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="pi">π</button> |
|
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="e">e</button> |
|
<button class="btn btn-secondary py-4 rounded" data-action="decimal">.</button> |
|
<button class="btn btn-number py-4 rounded col-span-2" data-action="equals">=</button> |
|
|
|
|
|
<button class="btn btn-number py-4 rounded" data-number="7">7</button> |
|
<button class="btn btn-number py-4 rounded" data-number="8">8</button> |
|
<button class="btn btn-number py-4 rounded" data-number="9">9</button> |
|
|
|
<button class="btn btn-number py-4 rounded" data-number="4">4</button> |
|
<button class="btn btn-number py-4 rounded" data-number="5">5</button> |
|
<button class="btn btn-number py-4 rounded" data-number="6">6</button> |
|
|
|
<button class="btn btn-number py-4 rounded" data-number="1">1</button> |
|
<button class="btn btn-number py-4 rounded" data-number="2">2</button> |
|
<button class="btn btn-number py-4 rounded" data-number="3">3</button> |
|
|
|
<button class="btn btn-number py-4 rounded" data-number="0">0</button> |
|
<button class="btn btn-number py-4 rounded" data-action="sign">±</button> |
|
</div> |
|
|
|
|
|
<div id="history-panel" class="hidden max-h-64 overflow-y-auto p-4 border-t"> |
|
<div class="text-center text-gray-500 mb-2">Calculation History</div> |
|
<div id="history-list"></div> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
|
|
const resultElement = document.getElementById('result'); |
|
const expressionElement = document.getElementById('expression'); |
|
const historyList = document.getElementById('history-list'); |
|
const tabs = document.querySelectorAll('.tab'); |
|
const scientificPanel = document.querySelector('.scientific-panel'); |
|
const scientificButtons = document.querySelectorAll('.scientific-btn'); |
|
const historyPanel = document.getElementById('history-panel'); |
|
const angleUnitButtons = document.querySelectorAll('.angle-unit'); |
|
|
|
|
|
let currentInput = '0'; |
|
let previousInput = ''; |
|
let operation = null; |
|
let resetInput = false; |
|
let angleMode = 'deg'; |
|
let calculationHistory = []; |
|
|
|
|
|
updateDisplay(); |
|
|
|
|
|
document.querySelectorAll('[data-number]').forEach(button => { |
|
button.addEventListener('click', () => { |
|
appendNumber(button.getAttribute('data-number')); |
|
}); |
|
}); |
|
|
|
|
|
document.querySelectorAll('[data-action]').forEach(button => { |
|
button.addEventListener('click', () => { |
|
const action = button.getAttribute('data-action'); |
|
|
|
switch(action) { |
|
case 'add': |
|
case 'subtract': |
|
case 'multiply': |
|
case 'divide': |
|
chooseOperation(action); |
|
break; |
|
case 'equals': |
|
compute(); |
|
break; |
|
case 'clear': |
|
clear(); |
|
break; |
|
case 'backspace': |
|
backspace(); |
|
break; |
|
case 'decimal': |
|
appendDecimal(); |
|
break; |
|
case 'sign': |
|
toggleSign(); |
|
break; |
|
case 'percentage': |
|
percentage(); |
|
break; |
|
case 'square': |
|
square(); |
|
break; |
|
case 'sqrt': |
|
squareRoot(); |
|
break; |
|
case 'power': |
|
power(); |
|
break; |
|
case 'sin': |
|
sin(); |
|
break; |
|
case 'cos': |
|
cos(); |
|
break; |
|
case 'tan': |
|
tan(); |
|
break; |
|
case 'asin': |
|
asin(); |
|
break; |
|
case 'acos': |
|
acos(); |
|
break; |
|
case 'atan': |
|
atan(); |
|
break; |
|
case 'log': |
|
log(); |
|
break; |
|
case 'ln': |
|
ln(); |
|
break; |
|
case 'factorial': |
|
factorial(); |
|
break; |
|
case 'pi': |
|
appendPi(); |
|
break; |
|
case 'e': |
|
appendE(); |
|
break; |
|
} |
|
}); |
|
}); |
|
|
|
|
|
tabs.forEach(tab => { |
|
tab.addEventListener('click', () => { |
|
const tabName = tab.getAttribute('data-tab'); |
|
|
|
|
|
tabs.forEach(t => t.classList.remove('tab-active')); |
|
tab.classList.add('tab-active'); |
|
|
|
|
|
if (tabName === 'scientific') { |
|
scientificPanel.classList.remove('hidden'); |
|
scientificButtons.forEach(btn => btn.classList.remove('hidden')); |
|
historyPanel.classList.add('hidden'); |
|
} else if (tabName === 'history') { |
|
scientificPanel.classList.add('hidden'); |
|
scientificButtons.forEach(btn => btn.classList.add('hidden')); |
|
historyPanel.classList.remove('hidden'); |
|
renderHistory(); |
|
} else { |
|
scientificPanel.classList.add('hidden'); |
|
scientificButtons.forEach(btn => btn.classList.add('hidden')); |
|
historyPanel.classList.add('hidden'); |
|
} |
|
}); |
|
}); |
|
|
|
|
|
angleUnitButtons.forEach(button => { |
|
button.addEventListener('click', () => { |
|
angleUnitButtons.forEach(btn => btn.classList.remove('active')); |
|
button.classList.add('active'); |
|
angleMode = button.getAttribute('data-unit'); |
|
}); |
|
}); |
|
|
|
|
|
document.addEventListener('keydown', (e) => { |
|
if (e.key >= '0' && e.key <= '9') { |
|
appendNumber(e.key); |
|
} else if (e.key === '.') { |
|
appendDecimal(); |
|
} else if (e.key === '+') { |
|
chooseOperation('add'); |
|
} else if (e.key === '-') { |
|
chooseOperation('subtract'); |
|
} else if (e.key === '*') { |
|
chooseOperation('multiply'); |
|
} else if (e.key === '/') { |
|
chooseOperation('divide'); |
|
} else if (e.key === 'Enter' || e.key === '=') { |
|
compute(); |
|
} else if (e.key === 'Escape') { |
|
clear(); |
|
} else if (e.key === 'Backspace') { |
|
backspace(); |
|
} else if (e.key === '%') { |
|
percentage(); |
|
} else if (e.key === '^') { |
|
power(); |
|
} |
|
}); |
|
|
|
|
|
function appendNumber(number) { |
|
if (currentInput === '0' || resetInput) { |
|
currentInput = number; |
|
resetInput = false; |
|
} else { |
|
currentInput += number; |
|
} |
|
updateDisplay(); |
|
} |
|
|
|
function appendDecimal() { |
|
if (resetInput) { |
|
currentInput = '0.'; |
|
resetInput = false; |
|
return; |
|
} |
|
|
|
if (currentInput.indexOf('.') === -1) { |
|
currentInput += '.'; |
|
} |
|
updateDisplay(); |
|
} |
|
|
|
function toggleSign() { |
|
currentInput = (parseFloat(currentInput) * -1).toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function clear() { |
|
currentInput = '0'; |
|
previousInput = ''; |
|
operation = null; |
|
updateDisplay(); |
|
} |
|
|
|
function backspace() { |
|
if (currentInput.length === 1 || (currentInput.length === 2 && currentInput.startsWith('-'))) { |
|
currentInput = '0'; |
|
} else { |
|
currentInput = currentInput.slice(0, -1); |
|
} |
|
updateDisplay(); |
|
} |
|
|
|
function chooseOperation(op) { |
|
if (currentInput === '0' && previousInput !== '') { |
|
operation = op; |
|
return; |
|
} |
|
|
|
if (previousInput === '') { |
|
previousInput = currentInput; |
|
} else if (operation) { |
|
const result = computeOperation(previousInput, currentInput, operation); |
|
previousInput = result.toString(); |
|
} |
|
|
|
operation = op; |
|
currentInput = '0'; |
|
updateDisplay(); |
|
} |
|
|
|
function compute() { |
|
if (operation === null || previousInput === '') return; |
|
|
|
const result = computeOperation(previousInput, currentInput, operation); |
|
|
|
|
|
const historyEntry = { |
|
expression: `${previousInput} ${getOperationSymbol(operation)} ${currentInput}`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
operation = null; |
|
previousInput = ''; |
|
resetInput = true; |
|
updateDisplay(); |
|
} |
|
|
|
function computeOperation(num1, num2, op) { |
|
const n1 = parseFloat(num1); |
|
const n2 = parseFloat(num2); |
|
|
|
switch(op) { |
|
case 'add': return n1 + n2; |
|
case 'subtract': return n1 - n2; |
|
case 'multiply': return n1 * n2; |
|
case 'divide': return n1 / n2; |
|
default: return n2; |
|
} |
|
} |
|
|
|
function percentage() { |
|
currentInput = (parseFloat(currentInput) / 100).toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function square() { |
|
const num = parseFloat(currentInput); |
|
const result = num * num; |
|
|
|
|
|
const historyEntry = { |
|
expression: `${num}²`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function squareRoot() { |
|
const num = parseFloat(currentInput); |
|
const result = Math.sqrt(num); |
|
|
|
|
|
const historyEntry = { |
|
expression: `√${num}`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function power() { |
|
previousInput = currentInput; |
|
currentInput = '0'; |
|
operation = 'power'; |
|
expressionElement.textContent = `${previousInput}^`; |
|
resultElement.textContent = currentInput; |
|
} |
|
|
|
function sin() { |
|
let num = parseFloat(currentInput); |
|
|
|
|
|
if (angleMode === 'deg') { |
|
num = degToRad(num); |
|
} else if (angleMode === 'grad') { |
|
num = gradToRad(num); |
|
} |
|
|
|
const result = Math.sin(num); |
|
|
|
|
|
const historyEntry = { |
|
expression: `sin(${currentInput}${angleMode})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function cos() { |
|
let num = parseFloat(currentInput); |
|
|
|
|
|
if (angleMode === 'deg') { |
|
num = degToRad(num); |
|
} else if (angleMode === 'grad') { |
|
num = gradToRad(num); |
|
} |
|
|
|
const result = Math.cos(num); |
|
|
|
|
|
const historyEntry = { |
|
expression: `cos(${currentInput}${angleMode})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function tan() { |
|
let num = parseFloat(currentInput); |
|
|
|
|
|
if (angleMode === 'deg') { |
|
num = degToRad(num); |
|
} else if (angleMode === 'grad') { |
|
num = gradToRad(num); |
|
} |
|
|
|
const result = Math.tan(num); |
|
|
|
|
|
const historyEntry = { |
|
expression: `tan(${currentInput}${angleMode})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function asin() { |
|
let num = parseFloat(currentInput); |
|
let result = Math.asin(num); |
|
|
|
|
|
if (angleMode === 'deg') { |
|
result = radToDeg(result); |
|
} else if (angleMode === 'grad') { |
|
result = radToGrad(result); |
|
} |
|
|
|
|
|
const historyEntry = { |
|
expression: `sin⁻¹(${currentInput})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function acos() { |
|
let num = parseFloat(currentInput); |
|
let result = Math.acos(num); |
|
|
|
|
|
if (angleMode === 'deg') { |
|
result = radToDeg(result); |
|
} else if (angleMode === 'grad') { |
|
result = radToGrad(result); |
|
} |
|
|
|
|
|
const historyEntry = { |
|
expression: `cos⁻¹(${currentInput})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function atan() { |
|
let num = parseFloat(currentInput); |
|
let result = Math.atan(num); |
|
|
|
|
|
if (angleMode === 'deg') { |
|
result = radToDeg(result); |
|
} else if (angleMode === 'grad') { |
|
result = radToGrad(result); |
|
} |
|
|
|
|
|
const historyEntry = { |
|
expression: `tan⁻¹(${currentInput})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function log() { |
|
const num = parseFloat(currentInput); |
|
const result = Math.log10(num); |
|
|
|
|
|
const historyEntry = { |
|
expression: `log(${currentInput})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function ln() { |
|
const num = parseFloat(currentInput); |
|
const result = Math.log(num); |
|
|
|
|
|
const historyEntry = { |
|
expression: `ln(${currentInput})`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function factorial() { |
|
const num = parseInt(currentInput); |
|
let result = 1; |
|
|
|
for (let i = 2; i <= num; i++) { |
|
result *= i; |
|
} |
|
|
|
|
|
const historyEntry = { |
|
expression: `${currentInput}!`, |
|
result: result |
|
}; |
|
calculationHistory.unshift(historyEntry); |
|
|
|
currentInput = result.toString(); |
|
updateDisplay(); |
|
} |
|
|
|
function appendPi() { |
|
if (currentInput === '0' || resetInput) { |
|
currentInput = Math.PI.toString(); |
|
resetInput = false; |
|
} else { |
|
currentInput += Math.PI.toString(); |
|
} |
|
updateDisplay(); |
|
} |
|
|
|
function appendE() { |
|
if (currentInput === '0' || resetInput) { |
|
currentInput = Math.E.toString(); |
|
resetInput = false; |
|
} else { |
|
currentInput += Math.E.toString(); |
|
} |
|
updateDisplay(); |
|
} |
|
|
|
|
|
function updateDisplay() { |
|
resultElement.textContent = currentInput; |
|
|
|
if (operation !== null) { |
|
expressionElement.textContent = `${previousInput} ${getOperationSymbol(operation)}`; |
|
} else { |
|
expressionElement.textContent = ''; |
|
} |
|
} |
|
|
|
function getOperationSymbol(op) { |
|
switch(op) { |
|
case 'add': return '+'; |
|
case 'subtract': return '−'; |
|
case 'multiply': return '×'; |
|
case 'divide': return '÷'; |
|
case 'power': return '^'; |
|
default: return ''; |
|
} |
|
} |
|
|
|
function degToRad(degrees) { |
|
return degrees * Math.PI / 180; |
|
} |
|
|
|
function radToDeg(radians) { |
|
return radians * 180 / Math.PI; |
|
} |
|
|
|
function gradToRad(grads) { |
|
return grads * Math.PI / 200; |
|
} |
|
|
|
function radToGrad(radians) { |
|
return radians * 200 / Math.PI; |
|
} |
|
|
|
function renderHistory() { |
|
historyList.innerHTML = ''; |
|
|
|
if (calculationHistory.length === 0) { |
|
historyList.innerHTML = '<div class="text-center text-gray-400 py-4">No history yet</div>'; |
|
return; |
|
} |
|
|
|
calculationHistory.forEach((item, index) => { |
|
const historyItem = document.createElement('div'); |
|
historyItem.className = 'history-item p-2 border-b hover:bg-gray-50'; |
|
historyItem.innerHTML = ` |
|
<div class="text-sm text-gray-500">${item.expression}</div> |
|
<div class="text-right font-semibold">${item.result}</div> |
|
`; |
|
|
|
historyItem.addEventListener('click', () => { |
|
currentInput = item.result.toString(); |
|
updateDisplay(); |
|
}); |
|
|
|
historyList.appendChild(historyItem); |
|
}); |
|
} |
|
</script> |
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=lior007/my-clock" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
</html> |