Began adding rationals

This commit is contained in:
PaddiM8 2020-12-13 17:15:57 +01:00
parent 1cbc5004d5
commit e9ae651572
3 changed files with 72 additions and 11 deletions

View File

@ -184,9 +184,11 @@ pub fn convert_unit(
.symbol_table
.insert(Stmt::VarDecl(DECL_UNIT.into(), Box::new(expr.clone())));
Ok(KalkNum::new(
eval_expr(context, &unit_def, "")?.value,
let num = eval_expr(context, &unit_def, "")?;
Ok(KalkNum::new_with_rational(
num.clone().value,
to_unit.into(),
num.get_internal_rational(),
))
} else {
Err(CalcError::InvalidUnit)
@ -243,7 +245,7 @@ fn eval_fn_call_expr(
};
if let Some((result, func_unit)) = prelude_func {
return Ok(KalkNum::new(
return Ok(KalkNum::new_without_rational(
result,
if unit.len() > 0 { unit } else { &func_unit },
));

View File

@ -1,11 +1,13 @@
use crate::ast::Expr;
use rug::ops::Pow;
use rug::Float;
use rug::Rational;
#[derive(PartialEq, Debug, Clone)]
pub struct KalkNum {
pub(crate) value: Float,
pub(crate) unit: String,
rational: Option<Rational>,
}
pub struct ScientificNotation {
@ -34,8 +36,25 @@ impl ScientificNotation {
impl KalkNum {
pub fn new(value: Float, unit: &str) -> Self {
Self {
value,
value: value.clone(),
unit: unit.to_string(),
rational: value.to_rational(),
}
}
pub(crate) fn new_with_rational(value: Float, unit: &str, rational: Option<Rational>) -> Self {
Self {
value: value.clone(),
unit: unit.to_string(),
rational: rational,
}
}
pub fn new_without_rational(value: Float, unit: &str) -> Self {
Self {
value: value.clone(),
unit: unit.to_string(),
rational: None,
}
}
@ -68,6 +87,16 @@ impl KalkNum {
&self.unit
}
pub fn get_rational(self) -> Option<(i64, i64)> {
let (numer, denom) = self.rational?.into_numer_denom();
Some((numer.to_i64()?, denom.to_i64()?))
}
pub fn get_internal_rational(self) -> Option<Rational> {
self.rational
}
pub fn has_unit(&self) -> bool {
self.unit.len() > 0
}
@ -109,32 +138,52 @@ impl KalkNum {
pub fn add(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value + right.value, &right.unit)
let mut num = KalkNum::new_without_rational(self.value + right.value, &right.unit);
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
num.rational = Some(left_rational + right_rational);
};
num
}
pub fn sub(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value - right.value, &right.unit)
let mut num = KalkNum::new_without_rational(self.value - right.value, &right.unit);
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
num.rational = Some(left_rational - right_rational);
};
num
}
pub fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value * right.value, &right.unit)
let mut num = KalkNum::new_without_rational(self.value * right.value, &right.unit);
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
num.rational = Some(left_rational * right_rational);
};
num
}
pub fn div(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value / right.value, &right.unit)
let mut num = KalkNum::new_without_rational(self.value / right.value, &right.unit);
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
num.rational = Some(left_rational / right_rational);
};
num
}
pub fn rem(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value % right.value, &right.unit)
KalkNum::new_without_rational(self.value % right.value, &right.unit)
}
pub fn pow(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
KalkNum::new(self.value.pow(right.value), &right.unit)
KalkNum::new_without_rational(self.value.pow(right.value), &right.unit)
}
}
@ -146,7 +195,11 @@ fn calculate_unit(
if left.has_unit() && right.has_unit() {
right.convert_to_unit(context, &left.unit)
} else {
Some(KalkNum::new(right.value, &left.unit))
Some(KalkNum::new_with_rational(
right.value,
&left.unit,
right.rational,
))
}
}

View File

@ -12,6 +12,12 @@ pub fn eval(parser: &mut parser::Context, input: &str) {
};
println!("{} {}", result_str, result.get_unit());
if result_str.contains(".") {
if let Some((numer, denom)) = result.get_rational() {
println!("{}/{}", numer, denom);
}
}
}
Ok(None) => print!(""),
Err(err) => print_calc_err(err),