use rust_decimal::prelude::*;
pub fn pct_change(beginning_value: Decimal, ending_value: Decimal) -> Option<Decimal> {
if beginning_value.is_zero() {
return None;
}
Some((ending_value - beginning_value) / beginning_value.abs()) }
pub fn apply_pct_change(value: Decimal, pct_change: Decimal) -> Decimal {
pct_change * value.abs() + value
}
#[cfg(test)]
mod tests {
use super::*;
use rust_decimal_macros::dec;
struct TestCase {
beginning_value: Decimal,
ending_value: Decimal,
pct_change: Decimal,
}
impl TestCase {
fn new(beginning_value: Decimal, ending_value: Decimal, pct_change: Decimal) -> Self {
TestCase {
beginning_value,
ending_value,
pct_change,
}
}
}
#[test]
fn test_pct_change_and_apply_pct_change() {
let cases = [
TestCase::new(dec!(1000), dec!(1500), dec!(0.5)), TestCase::new(dec!(1000), dec!(500), dec!(-0.5)), TestCase::new(dec!(1000), dec!(1000), dec!(0)), TestCase::new(dec!(1000), dec!(-1500), dec!(-2.5)), TestCase::new(dec!(-1000), dec!(1500), dec!(2.5)), ];
for case in &cases {
let pct_change_result = pct_change(case.beginning_value, case.ending_value);
assert_eq!(pct_change_result, Some(case.pct_change));
let apply_pct_change_result = apply_pct_change(case.beginning_value, case.pct_change);
assert_eq!(apply_pct_change_result, case.ending_value);
}
let result_zero = pct_change(dec!(0), dec!(1000)).unwrap_or(dec!(0));
assert_eq!(result_zero, dec!(0));
}
}