diff --git a/Maths/ReturnOnInvestment.js b/Maths/ReturnOnInvestment.js new file mode 100644 index 0000000000..ef75b8f160 --- /dev/null +++ b/Maths/ReturnOnInvestment.js @@ -0,0 +1,27 @@ +/** + * @function returnOnInvestment + * @description Calculates Return on Investment (ROI) as a percentage. + * ROI measures the profitability of an investment relative to its cost. + * Formula: ROI = (Gain - Cost) / Cost * 100 + * @param {number} gainFromInvestment - Total value gained from the investment + * @param {number} costOfInvestment - Total cost of the investment + * @return {number} ROI as a percentage + * @see https://www.investopedia.com/terms/r/returnoninvestment.asp + * @example returnOnInvestment(1000, 500) = 100 + * @example returnOnInvestment(500, 500) = 0 + * @example returnOnInvestment(200, 500) = -60 + */ +const returnOnInvestment = (gainFromInvestment, costOfInvestment) => { + if ( + typeof gainFromInvestment !== 'number' || + typeof costOfInvestment !== 'number' + ) { + throw new TypeError('Arguments must be numbers') + } + if (costOfInvestment <= 0) { + throw new RangeError('costOfInvestment must be greater than 0') + } + return ((gainFromInvestment - costOfInvestment) / costOfInvestment) * 100 +} + +export { returnOnInvestment } diff --git a/Maths/test/ReturnOnInvestment.test.js b/Maths/test/ReturnOnInvestment.test.js new file mode 100644 index 0000000000..d179bb6818 --- /dev/null +++ b/Maths/test/ReturnOnInvestment.test.js @@ -0,0 +1,35 @@ +import { returnOnInvestment } from '../ReturnOnInvestment' + +describe('returnOnInvestment', () => { + test('positive ROI when gain exceeds cost', () => { + expect(returnOnInvestment(1000, 500)).toBe(100) + }) + + test('zero ROI when gain equals cost', () => { + expect(returnOnInvestment(500, 500)).toBe(0) + }) + + test('negative ROI when gain is less than cost', () => { + expect(returnOnInvestment(200, 500)).toBe(-60) + }) + + test('total loss when gain is zero', () => { + expect(returnOnInvestment(0, 500)).toBe(-100) + }) + + test('throws RangeError for zero cost', () => { + expect(() => returnOnInvestment(1000, 0)).toThrow(RangeError) + }) + + test('throws RangeError for negative cost', () => { + expect(() => returnOnInvestment(1000, -100)).toThrow(RangeError) + }) + + test('throws TypeError for non-number gain', () => { + expect(() => returnOnInvestment('1000', 500)).toThrow(TypeError) + }) + + test('throws TypeError for non-number cost', () => { + expect(() => returnOnInvestment(1000, '500')).toThrow(TypeError) + }) +})