Design a Calculator class. The class should provide the mathematical operations of addition, subtraction, multiplication, division, and exponentiation. It should also allow consecutive operations to be performed using method chaining. The Calculator class constructor should accept a number which serves as the initial value of result.
Your Calculator class should have the following methods:
add - This method adds the given number value to the result and returns the updated Calculator.subtract - This method subtracts the given number value from the result and returns the updated Calculator.multiply - This method multiplies the result by the given number value and returns the updated Calculator.divide - This method divides the result by the given number value and returns the updated Calculator. If the passed value is 0, an error "Division by zero is not allowed" should be thrown.power - This method raises the result to the power of the given number value and returns the updated Calculator.getResult - This method returns the result.Solutions within 10-5 of the actual result are considered correct.
Example 1:
Input: actions = ["Calculator", "add", "subtract", "getResult"], values = [10, 5, 7] Output: 8 Explanation: new Calculator(10).add(5).subtract(7).getResult() // 10 + 5 - 7 = 8
Example 2:
Input: actions = ["Calculator", "multiply", "power", "getResult"], values = [2, 5, 2] Output: 100 Explanation: new Calculator(2).multiply(5).power(2).getResult() // (2 * 5) ^ 2 = 100
Example 3:
Input: actions = ["Calculator", "divide", "getResult"], values = [20, 0] Output: "Division by zero is not allowed" Explanation: new Calculator(20).divide(0).getResult() // 20 / 0 The error should be thrown because we cannot divide by zero.
Constraints:
actions is a valid JSON array of stringsvalues is a valid JSON array of numbers2 <= actions.length <= 2 * 1041 <= values.length <= 2 * 104 - 1actions[i] is one of "Calculator", "add", "subtract", "multiply", "divide", "power", and "getResult"When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The approach is to build a calculator that keeps a single, running total. Each time a new math operation is requested, it's immediately performed on this running total, which then becomes the new starting point for the next operation in the sequence.
Here's how the algorithm would work step-by-step:
class Calculator:
def __init__(self, initial_value):
# This initializes the calculator's state, setting the starting point for all calculations.
self.current_result = initial_value
def add(self, number_to_add):
self.current_result += number_to_add
# Returning 'self' is the core mechanism that allows for the chaining of method calls.
return self
def subtract(self, number_to_subtract):
self.current_result -= number_to_subtract
return self
def multiply(self, number_to_multiply):
self.current_result *= number_to_multiply
return self
def divide(self, number_to_divide_by):
# We must check for division by zero to prevent a runtime error, a critical safety measure.
if number_to_divide_by == 0:
raise ValueError("Cannot divide by zero.")
self.current_result /= number_to_divide_by
return self
def get_result(self):
# This final method provides access to the accumulated result after all chained operations.
return self.current_resultThe core idea is to create a calculator that maintains a running total internally. Each mathematical operation modifies this running total and then, crucially, returns the calculator object itself, allowing the next operation to be immediately performed on the new value.
Here's how the algorithm would work step-by-step:
class Calculator:
def __init__(self, initial_value):
# This holds the running total that gets updated by each operation in the chain.
self.current_total = initial_value
def add(self, number_to_add):
self.current_total += number_to_add
# Returning the object itself ('self') is the key to enabling method chaining.
return self
def subtract(self, number_to_subtract):
self.current_total -= number_to_subtract
return self
def multiply(self, number_to_multiply):
self.current_total *= number_to_multiply
return self
def divide(self, number_to_divide_by):
# It is critical to handle invalid mathematical operations like division by zero.
if number_to_divide_by == 0:
raise ValueError("Cannot divide by zero.")
self.current_total /= number_to_divide_by
return self
def get_result(self):
# This final method is called at the end of the chain to retrieve the final value.
return self.current_total| Case | How to Handle |
|---|---|
| Dividing the current result by zero. | The divide method must explicitly check if the input value is zero and throw the specified error. |
| A sequence of operations where mathematical precedence might be assumed, such as addition followed by multiplication. | The method chaining design strictly enforces a left-to-right evaluation order, ignoring standard mathematical operator precedence. |
| Operations that can introduce floating-point inaccuracies, such as dividing by 3. | The class uses standard floating-point arithmetic, and the problem's tolerance of 10^-5 accommodates for minor precision errors. |
| Multiplying the current result by zero at any point in the chain. | The result correctly becomes zero, which affects all subsequent chained operations. |
| Operations resulting in numbers that exceed the standard floating-point representation limits. | The result will become Infinity or -Infinity, which is the standard behavior for numeric overflow. |
| The current result is zero and the power method is called with a negative exponent. | This is an implicit division by zero, and the result correctly becomes Infinity based on standard library behavior. |
| The current result is a negative number and the power method is called with a fractional exponent. | This operation is undefined for real numbers, and the result correctly becomes NaN (Not a Number). |
| Chaining further operations after the result has become a special numeric value like Infinity or NaN. | Subsequent arithmetic operations will correctly propagate these special values according to standard IEEE 754 floating-point rules. |