diff --git a/Maths/SquareRoot.js b/Maths/SquareRoot.js index 0c50d9d3d7..d04115b43f 100644 --- a/Maths/SquareRoot.js +++ b/Maths/SquareRoot.js @@ -1,23 +1,29 @@ -/* - * Author: Rak Laptudirm - * - * https://en.wikipedia.org/wiki/Newton%27s_method - * - * Finding the square root of a number using Newton's method. +/** + * @function squareRoot + * @description Calculates the square root of a non-negative number + * using the Babylonian (Newton's) method without using Math.sqrt(). + * @param {number} n - A non-negative number + * @param {number} precision - Decimal places of precision (default: 10) + * @returns {number} - The square root of n + * @see https://en.wikipedia.org/wiki/Methods_of_computing_square_roots + * @example squareRoot(4) => 2 + * @example squareRoot(9) => 3 + * @example squareRoot(2) => 1.4142135624 */ - -function sqrt(num, precision = 4) { - if (!Number.isFinite(num)) { - throw new TypeError(`Expected a number, received ${typeof num}`) +const squareRoot = (n, precision = 10) => { + if (typeof n !== 'number' || isNaN(n) || n < 0) { + throw new TypeError('Input must be a non-negative number') } - if (!Number.isFinite(precision)) { - throw new TypeError(`Expected a number, received ${typeof precision}`) + if (!Number.isInteger(precision) || precision < 0) { + throw new TypeError('Precision must be a non-negative integer') } - let sqrt = 1 - for (let i = 0; i < precision; i++) { - sqrt -= (sqrt * sqrt - num) / (2 * sqrt) + if (n === 0 || n === 1) return n + let guess = n / 2 + const epsilon = Math.pow(10, -precision) + while (Math.abs(guess * guess - n) > epsilon) { + guess = (guess + n / guess) / 2 } - return sqrt + return parseFloat(guess.toFixed(precision)) } -export { sqrt } +export { squareRoot } diff --git a/Maths/test/SquareRoot.test.js b/Maths/test/SquareRoot.test.js index a85b3581b1..d5216dcace 100644 --- a/Maths/test/SquareRoot.test.js +++ b/Maths/test/SquareRoot.test.js @@ -1,36 +1,47 @@ -import { sqrt } from '../SquareRoot' +import { squareRoot } from '../SquareRoot.js' -test('Check SquareRoot of 4 is 2', () => { - const res = sqrt(4, 10) - expect(res).toBeCloseTo(2) -}) +describe('squareRoot', () => { + test('squareRoot(0) returns 0', () => { + expect(squareRoot(0)).toBe(0) + }) -test('Check SquareRoot of 2 is 1.4142135', () => { - const res = sqrt(2, 10) - expect(res).toBeCloseTo(1.4142135) -}) + test('squareRoot(1) returns 1', () => { + expect(squareRoot(1)).toBe(1) + }) -test('Check SquareRoot of 3.2 is 1.788854381999832', () => { - const res = sqrt(3.2, 10) - expect(res).toBeCloseTo(1.788854381999832) -}) + test('squareRoot(4) returns 2', () => { + expect(squareRoot(4)).toBe(2) + }) -test('Check SquareRoot of 1 is 1', () => { - const res = sqrt(1, 10) - expect(res).toBe(1) -}) + test('squareRoot(9) returns 3', () => { + expect(squareRoot(9)).toBe(3) + }) -test('Check SquareRoot of 144 is 12', () => { - const res = sqrt(144, 10) - expect(res).toBeCloseTo(12) -}) + test('squareRoot(16) returns 4', () => { + expect(squareRoot(16)).toBe(4) + }) -test('Check SquareRoot of 0 is 0', () => { - const res = sqrt(0, 10) - expect(res).toBeCloseTo(0) -}) + test('squareRoot(100) returns 10', () => { + expect(squareRoot(100)).toBe(10) + }) + + test('squareRoot(2) returns approximately 1.4142135624', () => { + expect(squareRoot(2)).toBeCloseTo(1.4142135624, 5) + }) + + test('squareRoot(0.25) returns 0.5', () => { + expect(squareRoot(0.25)).toBeCloseTo(0.5, 5) + }) + + test('throws TypeError for negative input', () => { + expect(() => squareRoot(-1)).toThrow(TypeError) + }) + + test('throws TypeError for non-number input', () => { + expect(() => squareRoot('4')).toThrow(TypeError) + }) -test('Check SquareRoot of 1000 is 31.62277', () => { - const res = sqrt(1000, 10) - expect(res).toBeCloseTo(31.62277) + test('throws TypeError for NaN', () => { + expect(() => squareRoot(NaN)).toThrow(TypeError) + }) })