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( """

Scientific Calculator

Perform basic and scientific mathematical calculations quickly and easily.

""" ) # -------------------------------------------------------- # 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( """ """ ) # ======================================================== # 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 )