diff --git a/.vscode/settings.json b/.vscode/settings.json index 9c79bdc..0e9a929 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,6 +23,16 @@ "tuple": "cpp", "type_traits": "cpp", "string_view": "cpp", - "vector": "cpp" + "vector": "cpp", + "algorithm": "cpp", + "memory": "cpp", + "random": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "numeric": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "streambuf": "cpp" } } diff --git a/languages/c++/code/nthRoot.cc b/languages/c++/code/nthRoot.cc index 674cdee..832f80c 100644 --- a/languages/c++/code/nthRoot.cc +++ b/languages/c++/code/nthRoot.cc @@ -2,39 +2,104 @@ #include #include -double nthRoot(double n, double x) { - double lastX; - double y = 1; // initial guess +std::string superscript[10] = { "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" }; - while (y != lastX) { - // f(y) = yⁿ - x - // f'(y) = nyⁿ⁻¹ - double f = std::pow(y, n) - x; - double fprime = n * std::pow(y, n - 1); +struct Result { + double result; + int maxIterations; + int iterationsUsed; +}; - lastX = y; - y -= f / fprime; +// See https://github.com/newtykins/the-honk/tree/main/maths/nth%20root.png +Result nthRoot(double n, double x, int maxIterations = 200) { + Result output; + output.result = 1; + output.maxIterations = maxIterations; + output.iterationsUsed = 0; + + double lastIteration = 0; + + for (int i = 0; i < maxIterations; i++) { + if (lastIteration == output.result) { + break; + } + + output.iterationsUsed += 1; + lastIteration = output.result; + output.result = ((lastIteration * (n - 1)) + (x * std::pow(lastIteration, 1 - n))) / n; } - return y; + return output; } -int promptForInteger(std::string letter) { +int fetchInput(std::string letter) { std::cout << "Please input a value for " + letter + ": "; - int input; + double input; std::cin >> input; return input; } +bool isInt(double n) { + return (int) n == n; +} + +std::string formatDouble(double input) { + std::string str = std::to_string(input); + str.erase(str.find_last_not_of('0') + 1, std::string::npos); + return str; +} + +std::string formatRadical(double n, double x) { + std::string formattedN = ""; + std::string formattedX = ""; + + if (isInt(n)) { + std::string nString = std::to_string((int) n); + + for (int i = 0; i < nString.length(); i++) { + int digit = (int) nString[i] - 48; + formattedN += superscript[digit]; + } + } else { + std::string nString = formatDouble(n); + + for (int i = 0; i < nString.length(); i++) { + try { + int digit = (int) nString[i] - 48; + formattedN += superscript[digit]; + } catch (const std::exception) { + formattedN += "˙"; + } + } + } + + if (isInt(x)) { + formattedX = std::to_string((int) x); + } else { + formattedX = formatDouble(x); + } + + return formattedN + "√" + formattedX; +} int main() { std::cout << "ⁿ√x\n"; - int n = promptForInteger("n"); - int x = promptForInteger("x"); + + double n = fetchInput("n"); + double x = fetchInput("x"); + + std::cout << "Please enter an amount of iterations to perform: "; + + int iterations; + std::cin >> iterations; // Make sure that cout prints to the highest precision possible std::cout.precision(std::numeric_limits::max_digits10); - std::cout << nthRoot(n, x); + + Result root = nthRoot(n, x, iterations); + + std::cout << "\n" << formatRadical(n, x) << " = " << root.result << "\n"; + std::cout << "Used " << root.iterationsUsed << " out of " << root.maxIterations << " iterations (:"; } diff --git a/languages/c++/code/squareForm.cc b/languages/c++/code/squareForm.cc index 25fbc75..f90fc58 100644 --- a/languages/c++/code/squareForm.cc +++ b/languages/c++/code/squareForm.cc @@ -44,17 +44,9 @@ std::string formatFraction(int numerator, int denominator) { // Format a double by cutting off as many trailing zeros as possible std::string formatDouble(double input) { - std::string output = std::to_string(abs(input)); - int pointIndex = output.find_last_of('.'); - int firstZeroIndex = output.find_last_not_of('0') + 1; - - if (firstZeroIndex - 1 == pointIndex) { - output.erase(firstZeroIndex - 1, std::string::npos); - } else { - output.erase(firstZeroIndex, std::string::npos); - } - - return output; + std::string str = std::to_string(input); + str.erase(str.find_last_not_of('0') + 1, std::string::npos); + return str; } // ax² + b^x + c^x -> a(x + p) + q diff --git a/languages/python/calculators/_helpers/floatInput.py b/languages/python/calculators/_helpers/floatInput.py index adf25c5..23d8c65 100644 --- a/languages/python/calculators/_helpers/floatInput.py +++ b/languages/python/calculators/_helpers/floatInput.py @@ -2,7 +2,7 @@ def floatInput(text): while True: try: - x = float(input(text + '\n')) + x = float(input(text)) return x except ValueError: print('You must input a float integer!\n') diff --git a/languages/python/calculators/_helpers/intInput.py b/languages/python/calculators/_helpers/intInput.py index b6fd0c3..c70476c 100644 --- a/languages/python/calculators/_helpers/intInput.py +++ b/languages/python/calculators/_helpers/intInput.py @@ -2,7 +2,7 @@ def intInput(text): while True: try: - x = int(input(text + '\n')) + x = int(input(text)) return x except ValueError: print('You must input an integer!\n') diff --git a/languages/python/calculators/nth root.py b/languages/python/calculators/nth root.py index eb8791c..b0291bb 100644 --- a/languages/python/calculators/nth root.py +++ b/languages/python/calculators/nth root.py @@ -1,16 +1,63 @@ -def nthRoot(n: int, x: int): - lastX = None - y = 1 # initial guess +from typing import Union +from _helpers import floatInput, intInput +from dataclasses import dataclass - while y != lastX: - # f(y) = yⁿ - x - # f'(y) = nyⁿ⁻¹ - f = (y ** n) - x - fprime = n * (y ** (n - 1)) - - lastX = y - y -= f / fprime +@dataclass +class Result: + result: Union[float, int] + maxIterations: int + iterationsUsed: int - return y +superscript = [ '⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹' ] -print(nthRoot(5, 6 ** 6)) +def formatRadical(n: float, x: float): + formattedN, formattedX = '', '' + + if int(n) == n: + nString = str(int(n)) + + for i in range(len(nString)): + digit = int(nString[i]) + formattedN += superscript[digit] + + else: + nString = str(n) + + for i in range(len(nString)): + try: + digit = int(nString[i]) + formattedN += superscript[digit] + except: + formattedN += '˙' + + if int(x) == x: + formattedX = str(int(x)) + else: + formattedX = str(x) + + return f"{formattedN}√{formattedX}" + +def nthRoot(n: float, x: float, maxIterations: int = 200) -> Result: + lastIteration, iteration, iterationsUsed = 0, 1, 0 + + for _ in range(maxIterations): + if lastIteration == iteration: + break + + iterationsUsed += 1 + lastIteration = iteration + iteration = ((iteration * (n - 1)) + (x * (iteration ** (1 - n)))) / n + + if int(iteration) == iteration: + iteration = int(iteration) + + return Result(iteration, maxIterations, iterationsUsed) + +print('ⁿ√x') +n = floatInput('Please input a value for n: ') +x = floatInput('Please input a value for x: ') +iterations = intInput('Please enter an amount of iterations to perform: ') +root = nthRoot(n, x, iterations) + +print(f'\n{formatRadical(n, x)} = {root.result}') +print(f'Used {root.iterationsUsed} out of {root.maxIterations} iterations (:') diff --git a/maths/nth root.png b/maths/nth root.png new file mode 100644 index 0000000..dc801bd Binary files /dev/null and b/maths/nth root.png differ