Drop files here
or click to upload
# calculator_app.py
"""
A calculator app with buttons like a traditional calculator.
Run with: streamlit run calculator_app.py
"""
import streamlit as st
# Page configuration
st.set_page_config(
page_title="Calculator App",
page_icon="🧮",
layout="centered"
)
# Initialize session state variables
if 'display' not in st.session_state:
st.session_state.display = "0"
if 'previous' not in st.session_state:
st.session_state.previous = None
if 'operation' not in st.session_state:
st.session_state.operation = None
if 'should_reset_display' not in st.session_state:
st.session_state.should_reset_display = False
if 'equation' not in st.session_state:
st.session_state.equation = ""
def handle_number(num):
"""Handle number button clicks"""
if st.session_state.should_reset_display or st.session_state.display == "0":
st.session_state.display = str(num)
st.session_state.should_reset_display = False
else:
# Limit display length to prevent overflow
if len(st.session_state.display) < 12:
st.session_state.display += str(num)
def handle_decimal():
"""Handle decimal point button"""
if st.session_state.should_reset_display:
st.session_state.display = "0."
st.session_state.should_reset_display = False
elif "." not in st.session_state.display:
st.session_state.display += "."
def handle_operation(op):
"""Handle operation buttons (+, -, ×, ÷)"""
# If there's a previous operation pending, calculate it first
if st.session_state.previous is not None and st.session_state.operation is not None and not st.session_state.should_reset_display:
calculate()
st.session_state.previous = float(st.session_state.display)
st.session_state.operation = op
st.session_state.should_reset_display = True
st.session_state.equation = f"{st.session_state.display} {op}"
def calculate():
"""Perform the calculation"""
if st.session_state.previous is None or st.session_state.operation is None:
return
current = float(st.session_state.display)
prev = st.session_state.previous
op = st.session_state.operation
try:
if op == "+":
result = prev + current
elif op == "-":
result = prev - current
elif op == "×":
result = prev * current
elif op == "÷":
if current == 0:
st.session_state.display = "Error"
st.session_state.previous = None
st.session_state.operation = None
st.session_state.should_reset_display = True
return
result = prev / current
# Format result nicely
if result.is_integer() and -1e12 < result < 1e12:
st.session_state.display = str(int(result))
else:
# Limit decimal places and use scientific notation for very large/small numbers
if abs(result) > 1e12 or (abs(result) < 1e-6 and result != 0):
st.session_state.display = f"{result:.6e}"
else:
st.session_state.display = f"{result:.10g}" # Remove trailing zeros
st.session_state.equation = f"{prev} {op} {current} ="
except OverflowError:
st.session_state.display = "Overflow"
except Exception:
st.session_state.display = "Error"
st.session_state.previous = None
st.session_state.operation = None
st.session_state.should_reset_display = True
def clear_all():
"""Clear all calculator state"""
st.session_state.display = "0"
st.session_state.previous = None
st.session_state.operation = None
st.session_state.should_reset_display = False
st.session_state.equation = ""
def clear_entry():
"""Clear current entry only"""
st.session_state.display = "0"
st.session_state.should_reset_display = False
def backspace():
"""Remove last digit"""
if not st.session_state.should_reset_display and st.session_state.display not in ["Error", "Overflow"]:
if len(st.session_state.display) > 1:
st.session_state.display = st.session_state.display[:-1]
else:
st.session_state.display = "0"
def toggle_sign():
"""Toggle positive/negative"""
if st.session_state.display not in ["Error", "Overflow", "0"]:
if st.session_state.display.startswith("-"):
st.session_state.display = st.session_state.display[1:]
else:
st.session_state.display = "-" + st.session_state.display
# UI Layout
st.title("🧮 Calculator")
# Display area with equation and result
display_container = st.container()
with display_container:
# Show the equation being built
st.caption(st.session_state.equation if st.session_state.equation else " ")
# Main display with custom styling
st.markdown(
f"""
<div style="
padding: 20px;
border-radius: 10px;
text-align: right;
font-size: 2em;
font-family: 'Courier New', monospace;
min-height: 60px;
margin-bottom: 20px;
word-wrap: break-word;
overflow-wrap: break-word;
">
{st.session_state.display}
</div>
""",
unsafe_allow_html=True
)
# Calculator button layout
# Row 1: Clear functions
col1, col2, col3, col4 = st.columns(4)
with col1:
st.button("C", on_click=clear_all, use_container_width=True, help="Clear All")
with col2:
st.button("CE", on_click=clear_entry, use_container_width=True, help="Clear Entry")
with col3:
st.button("⌫", on_click=backspace, use_container_width=True, help="Backspace")
with col4:
st.button("÷", on_click=lambda: handle_operation("÷"), use_container_width=True, type="secondary")
# Row 2: 7, 8, 9, ×
col1, col2, col3, col4 = st.columns(4)
with col1:
st.button("7", on_click=lambda: handle_number(7), use_container_width=True)
with col2:
st.button("8", on_click=lambda: handle_number(8), use_container_width=True)
with col3:
st.button("9", on_click=lambda: handle_number(9), use_container_width=True)
with col4:
st.button("×", on_click=lambda: handle_operation("×"), use_container_width=True, type="secondary")
# Row 3: 4, 5, 6, -
col1, col2, col3, col4 = st.columns(4)
with col1:
st.button("4", on_click=lambda: handle_number(4), use_container_width=True)
with col2:
st.button("5", on_click=lambda: handle_number(5), use_container_width=True)
with col3:
st.button("6", on_click=lambda: handle_number(6), use_container_width=True)
with col4:
st.button("-", on_click=lambda: handle_operation("-"), use_container_width=True, type="secondary")
# Row 4: 1, 2, 3, +
col1, col2, col3, col4 = st.columns(4)
with col1:
st.button("1", on_click=lambda: handle_number(1), use_container_width=True)
with col2:
st.button("2", on_click=lambda: handle_number(2), use_container_width=True)
with col3:
st.button("3", on_click=lambda: handle_number(3), use_container_width=True)
with col4:
st.button("+", on_click=lambda: handle_operation("+"), use_container_width=True, type="secondary")
# Row 5: +/-, 0, ., =
col1, col2, col3, col4 = st.columns(4)
with col1:
st.button("+/-", on_click=toggle_sign, use_container_width=True)
with col2:
st.button("0", on_click=lambda: handle_number(0), use_container_width=True)
with col3:
st.button(".", on_click=handle_decimal, use_container_width=True)
with col4:
st.button("=", on_click=calculate, use_container_width=True, type="primary")
# Additional scientific functions (optional row)
st.markdown("---")
st.caption("🔬 Scientific Functions")
col1, col2, col3, col4 = st.columns(4)
with col1:
if st.button("x²", use_container_width=True):
try:
val = float(st.session_state.display)
result = val ** 2
st.session_state.display = str(int(result)) if result.is_integer() else f"{result:.10g}"
st.session_state.equation = f"{val}² ="
st.session_state.should_reset_display = True
except:
st.session_state.display = "Error"
with col2:
if st.button("√x", use_container_width=True):
try:
val = float(st.session_state.display)
if val < 0:
st.session_state.display = "Error"
else:
result = val ** 0.5
st.session_state.display = str(int(result)) if result.is_integer() else f"{result:.10g}"
st.session_state.equation = f"√{val} ="
st.session_state.should_reset_display = True
except:
st.session_state.display = "Error"
with col3:
if st.button("1/x", use_container_width=True):
try:
val = float(st.session_state.display)
if val == 0:
st.session_state.display = "Error"
else:
result = 1 / val
st.session_state.display = f"{result:.10g}"
st.session_state.equation = f"1/{val} ="
st.session_state.should_reset_display = True
except:
st.session_state.display = "Error"
with col4:
if st.button("%", use_container_width=True):
try:
val = float(st.session_state.display)
result = val / 100
st.session_state.display = f"{result:.10g}"
st.session_state.equation = f"{val}% ="
st.session_state.should_reset_display = True
except:
st.session_state.display = "Error"
# Footer
st.markdown("---")
st.caption("💡 **Tip:** Click the buttons to perform calculations just like a traditional calculator!")
# Add custom CSS for better button styling
st.markdown("""
<style>
/* Make buttons taller */
.stButton > button {
height: 60px;
font-size: 20px;
font-weight: bold;
}
/* Style operation buttons */
.stButton > button[kind="secondary"] {
background-color: #ff6b6b;
color: white;
}
/* Style equals button */
.stButton > button[kind="primary"] {
background-color: #4CAF50;
color: white;
}
</style>
""", unsafe_allow_html=True)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?