Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
* [Word Break](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/word_break.rs)
* Financial
* [Present Value](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/present_value.rs)
* [Net Present Value](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/npv.rs)
* [Compound Interest](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/compound_interest.rs)
* [Payback Period](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/payback.rs)
* General
* [Convex Hull](https://github.com/TheAlgorithms/Rust/blob/master/src/general/convex_hull.rs)
* [Fisher Yates Shuffle](https://github.com/TheAlgorithms/Rust/blob/master/src/general/fisher_yates_shuffle.rs)
Expand Down
23 changes: 23 additions & 0 deletions src/financial/compound_interest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// compound interest is given by A = P(1+r/n)^nt
// where: A = Final Amount, P = Principal Amount, r = rate of interest,
// n = number of times interest is compounded per year and t = time (in years)

pub fn compound_interest(principal: f64, rate: f64, comp_per_year: u32, years: f64) -> f64 {
principal * (1.00 + rate / comp_per_year as f64).powf(comp_per_year as f64 * years)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_compound_interest() {
let principal = 1000.0;
let rate = 0.05; // 5% annual interest
let times_per_year = 4; // interest compounded quarterly
let years = 2.0; // 2 years tenure
let result = compound_interest(principal, rate, times_per_year, years);
assert!((result - 1104.486).abs() < 0.001); // expected value rounded up to 3 decimal
// places
}
}
6 changes: 6 additions & 0 deletions src/financial/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
mod compound_interest;
mod npv;
mod payback;
mod present_value;
pub use compound_interest::compound_interest;
pub use npv::npv;
pub use payback::payback;
pub use present_value::present_value;
44 changes: 44 additions & 0 deletions src/financial/npv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/// Calculates Net Present Value given a vector of cash flows and a discount rate.
/// cash_flows: Vector of f64 representing cash flows for each period.
/// rate: Discount rate as an f64 (e.g., 0.05 for 5%)

pub fn npv(cash_flows: &[f64], rate: f64) -> f64 {
cash_flows
.iter()
.enumerate()
.map(|(t, &cf)| cf / (1.00 + rate).powi(t as i32))
.sum()
}

// tests

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_npv_basic() {
let cash_flows = vec![-1000.0, 300.0, 400.0, -50.0];
let rate = 0.10;
let result = npv(&cash_flows, rate);
// Calculated value ≈ -434.25
assert!((result - (-434.25)).abs() < 0.05); // Allow small margin of error
}

#[test]
fn test_npv_zero_rate() {
let cash_flows = vec![100.0, 200.0, -50.0];
let rate = 0.0;
let result = npv(&cash_flows, rate);
assert!((result - 250.0).abs() < 0.05);
}

#[test]
fn test_npv_empty() {
// For empty cash flows: NPV should be 0
let cash_flows: Vec<f64> = vec![];
let rate = 0.05;
let result = npv(&cash_flows, rate);
assert_eq!(result, 0.0);
}
}
30 changes: 30 additions & 0 deletions src/financial/payback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// Returns the payback period in years
/// If investment is not paid back, returns None.

pub fn payback(cash_flow: &[f64]) -> Option<usize> {
let mut total = 0.00;
for (year, &cf) in cash_flow.iter().enumerate() {
total += cf;
if total >= 0.00 {
return Some(year);
}
}
None
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_payback() {
let cash_flows = vec![-1000.0, 300.0, 400.0, 500.0];
assert_eq!(payback(&cash_flows), Some(3)); // paid back in year 3
}

#[test]
fn test_no_payback() {
let cash_flows = vec![-1000.0, 100.0, 100.0, 100.0];
assert_eq!(payback(&cash_flows), None); // never paid back
}
}