From c3d24662946df4c413c620e9f31741f345b8c223 Mon Sep 17 00:00:00 2001 From: Inuka Wijerathna Date: Fri, 5 Jun 2026 10:43:25 +0530 Subject: [PATCH 1/2] Add ReturnOnInvestment to math --- math/returnoninvestment.go | 21 ++++++++++++++++++++ math/returnoninvestment_test.go | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 math/returnoninvestment.go create mode 100644 math/returnoninvestment_test.go diff --git a/math/returnoninvestment.go b/math/returnoninvestment.go new file mode 100644 index 000000000..fcbd3d66d --- /dev/null +++ b/math/returnoninvestment.go @@ -0,0 +1,21 @@ +// returnoninvestment.go +// description: Return on Investment (ROI) +// details: +// Return on Investment (ROI) measures the profitability of an investment +// relative to its cost, expressed as a percentage. +// Formula: ROI = (Gain - Cost) / Cost * 100 +// reference: https://www.investopedia.com/terms/r/returnoninvestment.asp +// author(s) [InukaWijerathna](https://github.com/InukaWijerathna) +// see returnoninvestment_test.go + +package math + +import "errors" + +// ReturnOnInvestment calculates the return on investment as a percentage. +func ReturnOnInvestment(gainFromInvestment, costOfInvestment float64) (float64, error) { + if costOfInvestment <= 0 { + return 0, errors.New("costOfInvestment must be greater than 0") + } + return (gainFromInvestment - costOfInvestment) / costOfInvestment * 100, nil +} diff --git a/math/returnoninvestment_test.go b/math/returnoninvestment_test.go new file mode 100644 index 000000000..2b2113943 --- /dev/null +++ b/math/returnoninvestment_test.go @@ -0,0 +1,34 @@ +package math + +import ( + "testing" +) + +func TestReturnOnInvestment(t *testing.T) { + tests := []struct { + name string + gain float64 + cost float64 + want float64 + wantErr bool + }{ + {"positive ROI", 1000, 500, 100, false}, + {"zero ROI", 500, 500, 0, false}, + {"negative ROI", 200, 500, -60, false}, + {"total loss", 0, 500, -100, false}, + {"zero cost", 1000, 0, 0, true}, + {"negative cost", 1000, -100, 0, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReturnOnInvestment(tt.gain, tt.cost) + if (err != nil) != tt.wantErr { + t.Errorf("ReturnOnInvestment() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr && got != tt.want { + t.Errorf("ReturnOnInvestment() = %v, want %v", got, tt.want) + } + }) + } +} From 201b55f8fec5c59ef1ce413ed86571d4020a71ca Mon Sep 17 00:00:00 2001 From: Inuka Wijerathna Date: Fri, 5 Jun 2026 15:48:57 +0530 Subject: [PATCH 2/2] Fix: use package-level error var and external test package --- math/returnoninvestment.go | 8 +++-- math/returnoninvestment_test.go | 54 +++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/math/returnoninvestment.go b/math/returnoninvestment.go index fcbd3d66d..8fb4c576b 100644 --- a/math/returnoninvestment.go +++ b/math/returnoninvestment.go @@ -10,12 +10,16 @@ package math -import "errors" +import ( + "errors" +) + +var ErrNonPositiveCost = errors.New("costOfInvestment must be greater than 0") // ReturnOnInvestment calculates the return on investment as a percentage. func ReturnOnInvestment(gainFromInvestment, costOfInvestment float64) (float64, error) { if costOfInvestment <= 0 { - return 0, errors.New("costOfInvestment must be greater than 0") + return 0, ErrNonPositiveCost } return (gainFromInvestment - costOfInvestment) / costOfInvestment * 100, nil } diff --git a/math/returnoninvestment_test.go b/math/returnoninvestment_test.go index 2b2113943..9a904f014 100644 --- a/math/returnoninvestment_test.go +++ b/math/returnoninvestment_test.go @@ -1,34 +1,44 @@ -package math +// returnoninvestment_test.go +// description: Tests for Return on Investment (ROI) +// author(s) [InukaWijerathna](https://github.com/InukaWijerathna) +// see returnoninvestment.go + +package math_test import ( "testing" + + "github.com/TheAlgorithms/Go/math" ) func TestReturnOnInvestment(t *testing.T) { - tests := []struct { - name string - gain float64 - cost float64 - want float64 - wantErr bool + var tests = []struct { + name string + gain float64 + cost float64 + expectedValue float64 + expectedError error }{ - {"positive ROI", 1000, 500, 100, false}, - {"zero ROI", 500, 500, 0, false}, - {"negative ROI", 200, 500, -60, false}, - {"total loss", 0, 500, -100, false}, - {"zero cost", 1000, 0, 0, true}, - {"negative cost", 1000, -100, 0, true}, + {"positive ROI", 1000, 500, 100, nil}, + {"zero ROI", 500, 500, 0, nil}, + {"negative ROI", 200, 500, -60, nil}, + {"total loss", 0, 500, -100, nil}, + {"zero cost", 1000, 0, 0, math.ErrNonPositiveCost}, + {"negative cost", 1000, -100, 0, math.ErrNonPositiveCost}, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ReturnOnInvestment(tt.gain, tt.cost) - if (err != nil) != tt.wantErr { - t.Errorf("ReturnOnInvestment() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !tt.wantErr && got != tt.want { - t.Errorf("ReturnOnInvestment() = %v, want %v", got, tt.want) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result, err := math.ReturnOnInvestment(test.gain, test.cost) + if result != test.expectedValue || test.expectedError != err { + t.Errorf("expected error: %v, got: %v; expected value: %v, got: %v", + test.expectedError, err, test.expectedValue, result) } }) } } + +func BenchmarkReturnOnInvestment(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = math.ReturnOnInvestment(1000, 500) + } +}