Improve rounding imprecision
This commit is contained in:
parent
8cfac98bc7
commit
a95fc61874
@ -47,10 +47,10 @@ pub fn cbrt(input: d128) -> d128 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pi() -> d128 {
|
fn pi() -> d128 {
|
||||||
d128!(3.141592653589793238462643383279503)
|
d128!(3.14159265358979323846264338327950288)
|
||||||
}
|
}
|
||||||
fn pi2() -> d128 {
|
fn pi2() -> d128 {
|
||||||
d128!(6.283185307179586476925286766559006)
|
d128!(6.283185307179586476925286766559005768)
|
||||||
}
|
}
|
||||||
fn pi_half() -> d128 {
|
fn pi_half() -> d128 {
|
||||||
d128!(1.570796326794896619231321691639751)
|
d128!(1.570796326794896619231321691639751)
|
||||||
@ -59,8 +59,8 @@ fn eulers_number() -> d128 {
|
|||||||
d128!(2.718281828459045235360287471352662)
|
d128!(2.718281828459045235360287471352662)
|
||||||
}
|
}
|
||||||
fn rounding_base() -> d128 {
|
fn rounding_base() -> d128 {
|
||||||
// DO NOT add a trailing zero here, it must be one less than the others
|
// DO NOT add trailing zeroes
|
||||||
d128!(0.00000000000000000000000000000001)
|
d128!(0.0000000000000000000000000000001)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sine of a [`struct@d128`]
|
/// Returns the sine of a [`struct@d128`]
|
||||||
@ -88,7 +88,7 @@ pub fn sin(mut input: d128) -> d128 {
|
|||||||
|
|
||||||
let unrounded_result = negative_correction * result;
|
let unrounded_result = negative_correction * result;
|
||||||
|
|
||||||
// This uses bankers rounding, but I *think* it's fine
|
// This uses bankers rounding
|
||||||
unrounded_result.quantize(rounding_base())
|
unrounded_result.quantize(rounding_base())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,8 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
|||||||
}
|
}
|
||||||
Ln => {
|
Ln => {
|
||||||
if child_answer.unit.category() == UnitType::NoType {
|
if child_answer.unit.category() == UnitType::NoType {
|
||||||
let result = child_answer.value.ln();
|
let unrounded_result = child_answer.value.ln();
|
||||||
|
let result = unrounded_result.quantize(unrounded_result * d128!(10));
|
||||||
Ok(Number::new(result, child_answer.unit))
|
Ok(Number::new(result, child_answer.unit))
|
||||||
} else {
|
} else {
|
||||||
Err("ln() only accepts UnitType::NoType".to_string())
|
Err("ln() only accepts UnitType::NoType".to_string())
|
||||||
@ -311,3 +312,62 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
|||||||
_ => Err(format!("Unexpected token {:?}", token)),
|
_ => Err(format!("Unexpected token {:?}", token)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::eval;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn eval_default<'a>(input: &'a str) -> Number {
|
||||||
|
let result = eval(input, true, false).unwrap();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
fn eval_num<'a>(input: &'a str) -> String {
|
||||||
|
let result = eval(input, true, false).unwrap();
|
||||||
|
assert_eq!(result.unit, Unit::NoUnit);
|
||||||
|
|
||||||
|
result.get_simplified_value().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_evaluations() {
|
||||||
|
assert_eq!(eval_num("-2(-3)"), "6");
|
||||||
|
assert_eq!(eval_num("-2(3)"), "-6");
|
||||||
|
assert_eq!(eval_num("(3)-2"), "1");
|
||||||
|
assert_eq!(eval_default("-1km to m"), Number::new(d128!(-1000), Unit::Meter));
|
||||||
|
assert_eq!(eval_num("2*-3*0.5"), "-3");
|
||||||
|
assert_eq!(eval_num("-3^2"), "-9");
|
||||||
|
assert_eq!(eval_num("-1+2"), "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_functions() {
|
||||||
|
assert_eq!(eval_num("cbrt(125)"), "5");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("sqrt(25)"), "5");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("log(100)"), "2");
|
||||||
|
assert_eq!(eval_num("log(2)"), "0.301029995663981195213738894724493");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("ln(1)"), "0");
|
||||||
|
assert_eq!(eval_num("ln(2)"), "0.693147180559945309417232121458177");
|
||||||
|
assert_eq!(eval_num("ln(e)"), "1");
|
||||||
|
assert_eq!(eval_num("ln(e^2)"), "2");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("round(1.4)"), "1");
|
||||||
|
assert_eq!(eval_num("round(1.6)"), "2");
|
||||||
|
assert_eq!(eval_num("round(1.5)"), "2");
|
||||||
|
assert_eq!(eval_num("round(2.5)"), "3");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("ceil(1.5)"), "2");
|
||||||
|
assert_eq!(eval_num("ceil(-1.5)"), "-1");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("floor(1.5)"), "1");
|
||||||
|
assert_eq!(eval_num("floor(-1.5)"), "-2");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("abs(-3)"), "3");
|
||||||
|
|
||||||
|
assert_eq!(eval_num("sin(2)"), "0.9092974268256816953960198659117");
|
||||||
|
assert_eq!(eval_num("sin(-2)"), "-0.9092974268256816953960198659117");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user