How to Create a Scientific Calculator for Engineering Use

Beginner 9 views Jul 16, 2026

Introduction

Engineers reach for a scientific calculator dozens of times a day — trig functions for structural angles, logarithms for decibel and pH calculations, memory keys for running totals, and a DEG/RAD toggle that a plain four-function calculator simply doesn't have. This tutorial builds a fully working scientific calculator in vanilla HTML, CSS, and JavaScript, with:

  • Trigonometric functions (sin, cos, tan) with inverse mode and a DEG/RAD toggle
  • log (base 10), ln (natural log), , , , 1/x, , n!
  • Constants π and e
  • Memory keys: MC, MR, M+, M−
  • Ans (recall the last result), parentheses, and auto-closing of unclosed parentheses

No libraries — just the Function() trick from the basic calculator, extended with real math functions.

Part 1: HTML Structure

The layout is split into two grids, the way real scientific calculators are: a function pad on top (5 columns) and a standard arithmetic keypad below it (4 columns).

index.html

html
HTML
<!DOCTYPEhtml>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"content="width=device-width, initial-scale=1.0">
 <title>Scientific Calculator</title>
 <link rel="stylesheet"href="style.css">
</head>
<body>
 <div class="calculator">
 <input type="text"id="display"placeholder="0"readonly>
 <!-- Scientific function pad -->
 <div class="sci-buttons">
 <button id="second-btn"onclick="toggleInverse()">2nd</button>
 <button id="mode-btn"onclick="toggleDegreeMode()">DEG</button>
 <button onclick="appendValue('(')">(</button>
 <button onclick="appendValue(')')">)</button>
 <button onclick="clearDisplay()">AC</button>
 <button onclick="appendValue('^2')">x²</button>
 <button onclick="appendValue('^')">x<sup>y</sup></button>
 <button onclick="insertFunction('sqrt')">√</button>
 <button onclick="appendValue('1/(')">1/x</button>
 <button onclick="deleteLast()">DEL</button>
 <button id="sin-btn"onclick="insertTrig('sin')">sin</button>
 <button id="cos-btn"onclick="insertTrig('cos')">cos</button>
 <button id="tan-btn"onclick="insertTrig('tan')">tan</button>
 <button onclick="insertFunction('log')">log</button>
 <button onclick="insertFunction('ln')">ln</button>
 <button onclick="appendValue(String(Math.PI))">π</button>
 <button onclick="appendValue(String(Math.E))">e</button>
 <button onclick="appendValue('!')">n!</button>
 <button onclick="insertFunction('exp')">e<sup>x</sup></button>
 <button onclick="appendValue(String(lastAnswer))">Ans</button>
 <button onclick="memoryClear()">MC</button>
 <button onclick="memoryRecall()">MR</button>
 <button onclick="memoryAdd()">M+</button>
 <button onclick="memorySubtract()">M−</button>
 <button onclick="appendValue('/100')">%</button>
 </div>
 <!-- Standard arithmetic keypad -->
 <div class="keypad">
 <button onclick="appendValue('7')">7</button>
 <button onclick="appendValue('8')">8</button>
 <button onclick="appendValue('9')">9</button>
 <button class="op"onclick="appendValue('÷')">÷</button>
 <button onclick="appendValue('4')">4</button>
 <button onclick="appendValue('5')">5</button>
 <button onclick="appendValue('6')">6</button>
 <button class="op"onclick="appendValue('×')">×</button>
 <button onclick="appendValue('1')">1</button>
 <button onclick="appendValue('2')">2</button>
 <button onclick="appendValue('3')">3</button>
 <button class="op"onclick="appendValue('−')">−</button>
 <button class="zero"onclick="appendValue('0')">0</button>
 <button onclick="appendValue('.')">.</button>
 <button class="op"onclick="appendValue('+')">+</button>
 <button class="full equals"onclick="calculate()">=</button>
 </div>
 </div>
 <script src="script.js"></script>
</body>
</html>

Key Points:

  • Two grids, one purpose: the sci-buttons grid holds functions and mode toggles; keypad holds digits and basic operators — mirrors how physical scientific calculators are laid out.
  • appendValue(String(Math.PI)): inserts the full-precision decimal value of π directly into the display, exactly like a real calculator does internally.
  • insertFunction() vs appendValue(): functions like sin, log, and need an opening parenthesis and an argument (sin(30)), so they get their own helper; digits, operators, and constants just get appended as-is.
  • id="sin-btn" etc.: these IDs let toggleInverse() rewrite the button labels to sin⁻¹, cos⁻¹, tan⁻¹ when 2nd is active.

Part 2: CSS Styling

css
CSS
*{
 margin:0;
 padding:0;
 box-sizing: border-box;
 font-family:"Segoe UI", Arial, sans-serif;
}
body{
 display: flex;
 justify-content: center;
 align-items: center;
 min-height:100vh;
 background:#eef1f5;
 padding:24px0;
}
.calculator{
 width:400px;
 max-width:100%;
 background:#ffffff;
 padding:20px;
 border-radius:20px;
 box-shadow:010px25pxrgba(0,0,0,0.12);
}
#display{
 width:100%;
 height:60px;
 margin-bottom:16px;
 border:2px solid #e2e8f0;
 border-radius:10px;
 font-size:26px;
 text-align: right;
 padding:10px14px;
 background:#f8fafc;
 color:#1e293b;
 outline: none;
}
/* Scientific function pad: 5 columns */
.sci-buttons{
 display: grid;
 grid-template-columns:repeat(5,1fr);
 gap:8px;
 margin-bottom:12px;
}
.sci-buttons button{
 height:42px;
 font-size:13.5px;
 border: none;
 border-radius:8px;
 background:#e2e8f0;
 color:#334155;
 font-weight:600;
 cursor: pointer;
 transition: all 0.15s ease;
}
.sci-buttons button:hover{background:#cbd5e1;}
/* Highlights the 2nd button while inverse mode is on */
.sci-buttons button.active{
 background:#3498db;
 color:#ffffff;
}
/* Standard arithmetic keypad: 4 columns */
.keypad{
 display: grid;
 grid-template-columns:repeat(4,1fr);
 gap:10px;
}
.keypad button{
 height:56px;
 border: none;
 border-radius:10px;
 background:#3498db;
 color:#ffffff;
 font-size:20px;
 font-weight:600;
 cursor: pointer;
 transition: all 0.15s ease;
}
.keypad button:hover{background:#2980b9;}
.keypad.op{background:#f39c12;}
.keypad.op:hover{background:#e08e0b;}
.keypad.equals{background:#27ae60;font-size:22px;}
.keypad.equals:hover{background:#219150;}
button:active{transform:scale(0.95);}
/* "0" spans two columns; "=" spans the full row */
.zero{grid-column: span 2;}
.full{grid-column: span 4;}

Key Points:

  • Two separate grids: .sci-buttons (5 columns) and .keypad (4 columns) stack in one card, so the CSS for each stays simple instead of one messy uneven grid.
  • Color coding: blue for digits, amber for operators, green for = — the same visual hierarchy engineers are used to on hardware calculators, so the eye finds "equals" instantly.
  • .active class: toggled by JavaScript to visually confirm when 2nd (inverse) mode is on.

Part 3: JavaScript Functionality

javascript
JAVASCRIPT
const display =document.getElementById("display");
let isDegreeMode =true;
let isInverseMode =false;
let memory =0;
let lastAnswer =0;
/* ---------- Angle conversion ---------- */
functiontoRadians(value){
 return isDegreeMode ?(value *Math.PI)/180: value;
}
functiontoOutputAngle(value){
 return isDegreeMode ?(value *180)/Math.PI: value;
}
/* ---------- Math functions used inside evaluated expressions ---------- */
functionsin(x){returnMath.sin(toRadians(x));}
functioncos(x){returnMath.cos(toRadians(x));}
functiontan(x){returnMath.tan(toRadians(x));}
functionasin(x){returntoOutputAngle(Math.asin(x));}
functionacos(x){returntoOutputAngle(Math.acos(x));}
functionatan(x){returntoOutputAngle(Math.atan(x));}
functionlog(x){returnMath.log10(x);}
functionln(x){returnMath.log(x);}
functionsqrt(x){returnMath.sqrt(x);}
functionexp(x){returnMath.exp(x);}
functionfact(n){
 n =Math.round(n);
 if(n <0)returnNaN;
 let result =1;
 for(let i =2; i <= n; i++) result *= i;
 return result;
}
/* ---------- Display editing ---------- */
functionappendValue(value){
 display.value+= value;
}
functioninsertFunction(name){
 display.value+= name +"(";
}
functioninsertTrig(fn){
 const name = isInverseMode ?"a"+ fn : fn;
 insertFunction(name);
}
functionclearDisplay(){
 display.value="";
}
functiondeleteLast(){
 display.value= display.value.slice(0,-1);
}
/* ---------- Mode toggles ---------- */
functiontoggleDegreeMode(){
 isDegreeMode =!isDegreeMode;
 document.getElementById("mode-btn").textContent= isDegreeMode ?"DEG":"RAD";
}
functiontoggleInverse(){
 isInverseMode =!isInverseMode;
 document.getElementById("second-btn").classList.toggle("active", isInverseMode);
 document.getElementById("sin-btn").textContent= isInverseMode ?"sin⁻¹":"sin";
 document.getElementById("cos-btn").textContent= isInverseMode ?"cos⁻¹":"cos";
 document.getElementById("tan-btn").textContent= isInverseMode ?"tan⁻¹":"tan";
}
/* ---------- Memory ---------- */
functionmemoryClear(){
 memory =0;
}
functionmemoryRecall(){
 appendValue(String(memory));
}
functionmemoryAdd(){
 const value =safeEvaluate(display.value);
 if(value !==null) memory += value;
}
functionmemorySubtract(){
 const value =safeEvaluate(display.value);
 if(value !==null) memory -= value;
}
/* ---------- Evaluation ---------- */
functiontoEvaluableExpression(rawExpression){
 return rawExpression
 .replace(/×/g,"*")
 .replace(/÷/g,"/")
 .replace(/\^/g,"**")
 .replace(/(\d+(\.\d+)?)!/g,"fact($1)");
}
// Closes any parentheses the user forgot to close, e.g. "sin(30" -> "sin(30)"
functionautoCloseParens(expression){
 const openCount =(expression.match(/\(/g)||[]).length;
 const closeCount =(expression.match(/\)/g)||[]).length;
 return expression +")".repeat(Math.max(0, openCount - closeCount));
}
functionsafeEvaluate(rawExpression){
 if(rawExpression.trim()==="")returnnull;
 try{
 const expression =autoCloseParens(toEvaluableExpression(rawExpression));
 const result =Function('"use strict"; return ('+ expression +')')();
 returnNumber.isFinite(result)? result :null;
 }catch(error){
 returnnull;
 }
}
functioncalculate(){
 const result =safeEvaluate(display.value);
 if(result ===null){
 display.value="Error";
 return;
 }
 const rounded =parseFloat(result.toFixed(10));
 display.value= rounded;
 lastAnswer = rounded;
}

Key Points:

  • Custom sin/cos/tan/log/ln/sqrt/exp: these are plain global functions, so when the display string (e.g. "sin(45)+sqrt(16)") is handed to Function(), it can resolve those names just like it resolves fact() in the basic calculator's bug fix.
  • DEG/RAD handled once, centrally: toRadians()/toOutputAngle() convert in and out of degrees, so every trig function respects whatever mode toggleDegreeMode() last set — you don't have to remember to convert at every call site.
  • autoCloseParens(): a genuinely useful addition — if you press sin(30 and hit = without typing the closing ), it's added automatically instead of throwing an error.
  • fact() via regex, not a button-inserted function call: n! is postfix in real math notation (5!, not fact(5)), so it's converted the same way × and ÷ are — a straight text substitution right before evaluation.
  • Ans and MR insert literal values, not variable names: appendValue(String(lastAnswer)) writes the actual number into the display string, which keeps the evaluator simple — no need to make lastAnswer or memory resolvable inside the evaluated expression itself.

Complete Project Structure

text
TXT
scientific-calculator/
├── index.html
├── style.css
└── script.js

How to Use

  1. Save the three files in one folder and open index.html in your browser.
  2. Toggle 2nd before pressing sin/cos/tan to get the inverse function (sin⁻¹, cos⁻¹, tan⁻¹).
  3. Toggle DEG/RAD depending on whether your angle values are in degrees or radians — this affects every trig calculation.
  4. Build expressions freely, e.g. sin(30)+sqrt(16)*log(100), then press =.
  5. Use M+/M− to accumulate a running total in memory, MR to recall it, and MC to reset it.
  6. Press Ans to reuse your last result in a new calculation.

Conclusion

This scientific calculator builds directly on the same string-evaluation technique as a basic four-function calculator, extended in three ways that matter for engineering work: a DEG/RAD-aware trig layer, function-call syntax (sin(, log(, √() for building nested expressions, and memory/Ans keys for multi-step calculations. The core lesson carries over: whatever the display shows and whatever JavaScript can actually evaluate are two different things, and the job of toEvaluableExpression() is to bridge that gap.

Technologies Used

HTML5 CSS3 JavaScript

Live Output

See the project in action below. This is the live preview of the code you just learned.

Output Preview