From 4db84aa441a803e8408848a2bb2231dd46c94e0b Mon Sep 17 00:00:00 2001 From: bakk Date: Mon, 17 May 2021 23:55:20 +0200 Subject: [PATCH] Basic rounding for calculus functions --- kalk/src/calculus.rs | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/kalk/src/calculus.rs b/kalk/src/calculus.rs index 92964c5..64271f7 100644 --- a/kalk/src/calculus.rs +++ b/kalk/src/calculus.rs @@ -22,7 +22,9 @@ pub fn derive_func( let f_x = interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_without_h], unit)?; - Ok(f_x_h.sub(context, f_x).div(context, (2f64 * H).into())) + Ok(round( + f_x_h.sub(context, f_x).div(context, (2f64 * H).into()), + )) } pub fn integrate( @@ -53,7 +55,13 @@ pub fn integrate( Box::new(Expr::Literal(1f64)), )); - simpsons_rule(context, a, b, expr, integration_variable.unwrap()) + Ok(round(simpsons_rule( + context, + a, + b, + expr, + integration_variable.unwrap(), + )?)) } /// Composite Simpson's 3/8 rule @@ -90,3 +98,26 @@ fn simpsons_rule( Ok(result) } + +/// Basic up/down rounding from 0.00xxx or 0.999xxx or xx.000xxx, etc. +fn round(num: KalkNum) -> KalkNum { + let fract = num.value.clone().fract(); + let floored = num.value.clone().floor(); + + // If it's zero something, don't do the rounding as aggressively. + let (limit_floor, limit_ceil) = if floored.clone() == 0 { + (-15, -5) + } else { + (-4, -6) + }; + + if fract.clone().log10() < limit_floor { + // If eg. 0.00xxx + return KalkNum::new(floored, &num.unit); + } else if (1f64 - fract).log10() < limit_ceil { + // If eg. 0.999 + return KalkNum::new(num.value.clone().ceil(), &num.unit); + } else { + return num; + } +}