Challenge

Scientific Calculator

Below is the implementation of a Scientific Calculator based on your requirements. It includes all operations and adheres to Object-Oriented Programming (OOP) principles. Additionally, I have provided an explanation of how OOP principles are applied.


Scientific Calculator

1. Calculator Class

import java.io.*;
import java.util.*;
import java.util.Scanner;
import java.lang.Math;

class ScientificCalculator {
    private double memory; // Memory for storing a number
    private List<String> history; // List to store calculations

    // Constructor
    public ScientificCalculator() {
        this.memory = 0.0;
        this.history = new ArrayList<>();
    }

    // Perform addition
    public double add(double a, double b) {
        double result = a + b;
        saveHistory("Addition: " + a + " + " + b + " = " + result);
        return result;
    }

    // Perform subtraction
    public double subtract(double a, double b) {
        double result = a - b;
        saveHistory("Subtraction: " + a + " - " + b + " = " + result);
        return result;
    }

    // Perform multiplication
    public double multiply(double a, double b) {
        double result = a * b;
        saveHistory("Multiplication: " + a + " * " + b + " = " + result);
        return result;
    }

    // Perform division
    public double divide(double a, double b) {
        if (b == 0) {
            saveHistory("Division by zero error");
            throw new ArithmeticException("Cannot divide by zero");
        }
        double result = a / b;
        saveHistory("Division: " + a + " / " + b + " = " + result);
        return result;
    }

    // Perform power calculation
    public double power(double base, double exponent) {
        double result = Math.pow(base, exponent);
        saveHistory(base + " raised to the power of " + exponent + " = " + result);
        return result;
    }

    // Perform square root
    public double squareRoot(double a) {
        if (a < 0) {
            saveHistory("Square root of negative number error");
            throw new ArithmeticException("Cannot calculate the square root of a negative number");
        }
        double result = Math.sqrt(a);
        saveHistory("Square root of " + a + " = " + result);
        return result;
    }

    // Perform nth root
    public double nthRoot(double a, double n) {
        if (a < 0 && n % 2 == 0) {
            saveHistory("Nth root of negative number error");
            throw new ArithmeticException("Cannot calculate the even root of a negative number");
        }
        double result = Math.pow(a, 1.0 / n);
        saveHistory("Nth root of " + a + " with root " + n + " = " + result);
        return result;
    }

    // Perform logarithmic calculations
    public double log(double a) {
        if (a <= 0) {
            saveHistory("Logarithm of non-positive number error");
            throw new ArithmeticException("Logarithm is undefined for non-positive numbers");
        }
        double result = Math.log10(a);
        saveHistory("Log10 of " + a + " = " + result);
        return result;
    }

    public double naturalLog(double a) {
        if (a <= 0) {
            saveHistory("Natural logarithm of non-positive number error");
            throw new ArithmeticException("Natural logarithm is undefined for non-positive numbers");
        }
        double result = Math.log(a);
        saveHistory("Natural log of " + a + " = " + result);
        return result;
    }

    // Trigonometric calculations
    public double sin(double angle) {
        double result = Math.sin(Math.toRadians(angle));
        saveHistory("Sine of " + angle + " degrees = " + result);
        return result;
    }

    public double inverseSin(double value) {
        if (value < -1 || value > 1) {
            saveHistory("Inverse sine of out-of-range value error");
            throw new ArithmeticException("Value out of range for inverse sine");
        }
        double result = Math.toDegrees(Math.asin(value));
        saveHistory("Inverse sine of " + value + " = " + result + " degrees");
        return result;
    }

    public double cos(double angle) {
        double result = Math.cos(Math.toRadians(angle));
        saveHistory("Cosine of " + angle + " degrees = " + result);
        return result;
    }

    public double inverseCos(double value) {
        if (value < -1 || value > 1) {
            saveHistory("Inverse cosine of out-of-range value error");
            throw new ArithmeticException("Value out of range for inverse cosine");
        }
        double result = Math.toDegrees(Math.acos(value));
        saveHistory("Inverse cosine of " + value + " = " + result + " degrees");
        return result;
    }

    public double tan(double angle) {
        double result = Math.tan(Math.toRadians(angle));
        saveHistory("Tangent of " + angle + " degrees = " + result);
        return result;
    }

    public double inverseTan(double value) {
        double result = Math.toDegrees(Math.atan(value));
        saveHistory("Inverse tangent of " + value + " = " + result + " degrees");
        return result;
    }

    // Memory operations
    public void storeMemory(double value) {
        memory = value;
        saveHistory("Stored " + value + " in memory");
    }

    public double recallMemory() {
        saveHistory("Recalled " + memory + " from memory");
        return memory;
    }

    // Decimal to Binary
    public String decimalToBinary(int value) {
        String result = Integer.toBinaryString(value);
        saveHistory("Decimal to Binary: " + value + " = " + result);
        return result;
    }

    // Binary to Decimal
    public int binaryToDecimal(String value) {
        int result = Integer.parseInt(value, 2);
        saveHistory("Binary to Decimal: " + value + " = " + result);
        return result;
    }

    // SIP calculations
    public double calculateSIP(double monthlyInvestment, double rate, int years) {
        double r = rate / 100 / 12;
        int n = years * 12;
        double result = monthlyInvestment * ((Math.pow(1 + r, n) - 1) / r) * (1 + r);
        saveHistory("SIP Calculation: Monthly=" + monthlyInvestment + ", Rate=" + rate + "%, Years=" + years + " = " + result);
        return result;
    }

    // Save history to file
    private void saveHistory(String entry) {
        history.add(entry);
        try (FileWriter writer = new FileWriter("CalculationsHistory.txt", true)) {
            writer.write(entry + "\n");
        } catch (IOException e) {
            System.out.println("Error writing to history file: " + e.getMessage());
        }
    }

    // Display all history
    public void displayHistory() {
        System.out.println("Calculation History:");
        for (String entry : history) {
            System.out.println(entry);
        }
    }
}


Driver Program

public class Main {
    public static void main(String[] args) {
        ScientificCalculator calculator = new ScientificCalculator();
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("\nChoose an operation:");
            System.out.println("1: Add (+), 2: Subtract (-), 3: Multiply (*), 4: Divide (/), 5: Power (^), 6: Sqrt, 7: Nrt, 8: Log, 9: Logn");
            System.out.println("10: Sin, 11: Isin, 12: Cos, 13: Icos, 14: Tan, 15: Itan, 16: Store Memory, 17: Recall Memory");
            System.out.println("18: Decimal to Binary, 19: Binary to Decimal, 20: SIP Calculation, 21: Show History, 22: Exit");
            int choice = scanner.nextInt();

            try {
                switch (choice) {
                    case 1 -> System.out.println(calculator.add(scanner.nextDouble(), scanner.nextDouble()));
                    case 2 -> System.out.println(calculator.subtract(scanner.nextDouble(), scanner.nextDouble()));
                    case 3 -> System.out.println(calculator.multiply(scanner.nextDouble(), scanner.nextDouble()));
                    case 4 -> System.out.println(calculator.divide(scanner.nextDouble(), scanner.nextDouble()));
                    case 5 -> System.out.println(calculator.power(scanner.nextDouble(), scanner.nextDouble()));
                    case 6 -> System.out.println(calculator.squareRoot(scanner.nextDouble()));
                    case 7 -> System.out.println(calculator.nthRoot(scanner.nextDouble(), scanner.nextDouble()));
                    case 8 -> System.out.println(calculator.log(scanner.nextDouble()));
                    case 9 -> System.out.println(calculator.naturalLog(scanner.nextDouble()));
                    case 10 -> System.out.println(calculator.sin(scanner.nextDouble()));
                    case 11 -> System.out.println(calculator.inverseSin(scanner.nextDouble()));
                    case 12 -> System.out.println(calculator.cos(scanner.nextDouble()));
                    case 13 -> System.out.println(calculator.inverseCos(scanner.nextDouble()));
                    case 14 -> System.out.println(calculator.tan(scanner.nextDouble()));
                    case 15 -> System.out.println(calculator.inverseTan(scanner.nextDouble()));
                    case 16 -> calculator.storeMemory(scanner.nextDouble());
                    case 17 -> System.out.println(calculator.recallMemory());
                    case 18 -> System.out.println(calculator.decimalToBinary(scanner.nextInt()));
                    case 19 -> System.out.println(calculator.binaryToDecimal(scanner.next()));
                    case 20 -> System.out.println(calculator.calculateSIP(scanner.nextDouble(), scanner.nextDouble(), scanner.nextInt()));
                    case 21 -> calculator.displayHistory();
                    case 22 -> {
                        System.out.println("Exiting...");
                        scanner.close();
                        return;
                    }
                    default -> System.out.println("Invalid choice. Try again.");
                }
            } catch (Exception e) {
                System.out.println("Error: " + e.getMessage());
            }
        }
    }
}


OOP Principles in Use

  1. Encapsulation:

    • Private fields (memory, history) ensure data protection. Access is through public methods.
    • Example: storeMemory() encapsulates the memory logic.
  2. Abstraction:

    • Only relevant methods are exposed, hiding implementation details.
    • Example: The add() method hides how addition is performed internally.
  3. Inheritance:

    • Potential future extensions can use inheritance for adding new operations.
  4. Polymorphism:

    • Overloaded methods for different operations.
    • Example: log() and naturalLog() provide different logarithmic operations.
  5. Modularity:

    • Each operation is a separate method, making the code easy to maintain and extend.

This implementation handles all required operations and adheres to OOP principles effectively! Let me know if you'd like further enhancements or additional features.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.