Calculator / app.py
BasitAliii's picture
Update app.py
fcc1902 verified
Raw History Blame Contribute Delete
14.5 kB
import math
import gradio as gr
import spaces
# ============================================================
# ZeroGPU Compatibility
# ============================================================
@spaces.GPU
def gpu_startup_check():
"""
ZeroGPU startup compatibility function.
The scientific calculator itself does not require GPU.
This function exists because Hugging Face ZeroGPU
requires at least one @spaces.GPU function.
"""
return True
# ============================================================
# Operations
# ============================================================
OPERATIONS = [
"Addition (+)",
"Subtraction (-)",
"Multiplication (×)",
"Division (÷)",
"Power (xʸ)",
"Square Root (√x)",
"Logarithm (log₁₀)",
"Natural Log (ln)",
"Sine (sin)",
"Cosine (cos)",
"Tangent (tan)",
"Factorial (n!)",
]
BINARY_OPERATIONS = {
"Addition (+)",
"Subtraction (-)",
"Multiplication (×)",
"Division (÷)",
"Power (xʸ)",
}
# ============================================================
# Number Formatting
# ============================================================
def format_number(value):
if isinstance(value, int):
return str(value)
if isinstance(value, float):
if not math.isfinite(value):
return str(value)
if value.is_integer():
return str(int(value))
return f"{value:.12g}"
return str(value)
# ============================================================
# Scientific Calculator
# ============================================================
def calculate(operation, num1, num2):
# --------------------------------------------------------
# Validate first number
# --------------------------------------------------------
if num1 is None:
return "Please enter the first number.", ""
try:
num1 = float(num1)
except (TypeError, ValueError):
return "Error: Invalid first number.", ""
# --------------------------------------------------------
# Validate second number for binary operations
# --------------------------------------------------------
if operation in BINARY_OPERATIONS:
if num2 is None:
return "Please enter the second number.", ""
try:
num2 = float(num2)
except (TypeError, ValueError):
return "Error: Invalid second number.", ""
# ========================================================
# Addition
# ========================================================
if operation == "Addition (+)":
result = num1 + num2
return (
format_number(result),
f"{format_number(num1)} + {format_number(num2)} = "
f"{format_number(result)}"
)
# ========================================================
# Subtraction
# ========================================================
if operation == "Subtraction (-)":
result = num1 - num2
return (
format_number(result),
f"{format_number(num1)} - {format_number(num2)} = "
f"{format_number(result)}"
)
# ========================================================
# Multiplication
# ========================================================
if operation == "Multiplication (×)":
result = num1 * num2
return (
format_number(result),
f"{format_number(num1)} × {format_number(num2)} = "
f"{format_number(result)}"
)
# ========================================================
# Division
# ========================================================
if operation == "Division (÷)":
if num2 == 0:
return "Error: Cannot divide by zero.", ""
result = num1 / num2
return (
format_number(result),
f"{format_number(num1)} ÷ {format_number(num2)} = "
f"{format_number(result)}"
)
# ========================================================
# Power
# ========================================================
if operation == "Power (xʸ)":
try:
result = num1 ** num2
if isinstance(result, complex):
return (
"Error: Complex numbers are not supported.",
""
)
if not math.isfinite(result):
return (
"Error: Result is too large.",
""
)
return (
format_number(result),
f"{format_number(num1)} ^ {format_number(num2)} = "
f"{format_number(result)}"
)
except (OverflowError, ValueError):
return (
"Error: Cannot calculate this power.",
""
)
# ========================================================
# Square Root
# ========================================================
if operation == "Square Root (√x)":
if num1 < 0:
return (
"Error: Square root of a negative number is not real.",
""
)
result = math.sqrt(num1)
return (
format_number(result),
f"√{format_number(num1)} = "
f"{format_number(result)}"
)
# ========================================================
# Logarithm Base 10
# ========================================================
if operation == "Logarithm (log₁₀)":
if num1 <= 0:
return (
"Error: Logarithm requires a positive number.",
""
)
result = math.log10(num1)
return (
format_number(result),
f"log₁₀({format_number(num1)}) = "
f"{format_number(result)}"
)
# ========================================================
# Natural Logarithm
# ========================================================
if operation == "Natural Log (ln)":
if num1 <= 0:
return (
"Error: Natural logarithm requires a positive number.",
""
)
result = math.log(num1)
return (
format_number(result),
f"ln({format_number(num1)}) = "
f"{format_number(result)}"
)
# ========================================================
# Sine
# ========================================================
if operation == "Sine (sin)":
result = math.sin(math.radians(num1))
if abs(result) < 1e-12:
result = 0.0
return (
format_number(result),
f"sin({format_number(num1)}°) = "
f"{format_number(result)}"
)
# ========================================================
# Cosine
# ========================================================
if operation == "Cosine (cos)":
result = math.cos(math.radians(num1))
if abs(result) < 1e-12:
result = 0.0
return (
format_number(result),
f"cos({format_number(num1)}°) = "
f"{format_number(result)}"
)
# ========================================================
# Tangent
# ========================================================
if operation == "Tangent (tan)":
radians = math.radians(num1)
if abs(math.cos(radians)) < 1e-12:
return (
"Error: Tangent is undefined at this angle.",
""
)
result = math.tan(radians)
if abs(result) < 1e-12:
result = 0.0
return (
format_number(result),
f"tan({format_number(num1)}°) = "
f"{format_number(result)}"
)
# ========================================================
# Factorial
# ========================================================
if operation == "Factorial (n!)":
if num1 < 0:
return (
"Error: Factorial requires a non-negative number.",
""
)
if not num1.is_integer():
return (
"Error: Factorial requires a whole number.",
""
)
if num1 > 170:
return (
"Error: Number is too large for factorial.",
""
)
result = math.factorial(int(num1))
return (
format_number(result),
f"{format_number(num1)}! = "
f"{format_number(result)}"
)
return "Error: Invalid operation.", ""
# ============================================================
# Second Number Visibility
# ============================================================
def update_second_number(operation):
if operation in BINARY_OPERATIONS:
return gr.Number(
label="Second Number",
placeholder="Enter second number",
visible=True
)
return gr.Number(
label="Second Number",
placeholder="Not required",
visible=False
)
# ============================================================
# Clear Calculator
# ============================================================
def clear_calculator():
return (
None,
None,
"Addition (+)",
"",
""
)
# ============================================================
# Custom CSS
# ============================================================
CUSTOM_CSS = """
body {
background: #f5f7fb;
}
.gradio-container {
max-width: 1100px !important;
margin: auto !important;
padding: 20px !important;
}
.header {
text-align: center;
padding: 25px 15px;
margin-bottom: 20px;
}
.header h1 {
font-size: 38px;
font-weight: 700;
margin-bottom: 8px;
}
.header p {
font-size: 16px;
opacity: 0.75;
}
.calc-card {
border: 1px solid #e5e7eb;
border-radius: 18px;
padding: 25px;
background: white;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.06);
}
.result-box textarea {
font-size: 24px !important;
font-weight: 600 !important;
text-align: center !important;
}
.calculation-box textarea {
font-size: 17px !important;
text-align: center !important;
}
.footer {
text-align: center;
margin-top: 25px;
padding: 15px;
font-size: 14px;
opacity: 0.65;
}
@media (max-width: 700px) {
.gradio-container {
padding: 10px !important;
}
.header h1 {
font-size: 30px;
}
.calc-card {
padding: 18px;
}
}
"""
# ============================================================
# Gradio Application
# ============================================================
with gr.Blocks(
title="Scientific Calculator"
) as app:
# --------------------------------------------------------
# Header
# --------------------------------------------------------
gr.HTML(
"""
<div class="header">
<h1>Scientific Calculator</h1>
<p>
Perform basic and scientific mathematical
calculations quickly and easily.
</p>
</div>
"""
)
# --------------------------------------------------------
# Main Layout
# --------------------------------------------------------
with gr.Row():
# ====================================================
# Calculator Input
# ====================================================
with gr.Column(elem_classes="calc-card"):
gr.Markdown("### Calculator")
operation = gr.Dropdown(
choices=OPERATIONS,
value="Addition (+)",
label="Select Operation"
)
num1 = gr.Number(
label="First Number",
placeholder="Enter first number"
)
num2 = gr.Number(
label="Second Number",
placeholder="Enter second number"
)
with gr.Row():
calculate_button = gr.Button(
"Calculate",
variant="primary"
)
clear_button = gr.Button(
"Clear",
variant="secondary"
)
# ====================================================
# Result
# ====================================================
with gr.Column(elem_classes="calc-card"):
gr.Markdown("### Result")
result = gr.Textbox(
label="Answer",
placeholder="Your result will appear here",
interactive=False,
elem_classes="result-box"
)
calculation = gr.Textbox(
label="Calculation",
placeholder="Calculation details will appear here",
interactive=False,
elem_classes="calculation-box"
)
# --------------------------------------------------------
# Footer
# --------------------------------------------------------
gr.HTML(
"""
<div class="footer">
Scientific Calculator • Python + Gradio
</div>
"""
)
# ========================================================
# Events
# ========================================================
operation.change(
fn=update_second_number,
inputs=operation,
outputs=num2
)
calculate_button.click(
fn=calculate,
inputs=[operation, num1, num2],
outputs=[result, calculation]
)
clear_button.click(
fn=clear_calculator,
inputs=[],
outputs=[
num1,
num2,
operation,
result,
calculation
]
)
# ============================================================
# Launch
# ============================================================
if __name__ == "__main__":
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
ssr_mode=False,
css=CUSTOM_CSS
)