diff --git a/src/quantity/scalar/f64base.rs b/src/quantity/scalar/f64base.rs index 4695e67..5e9bcaf 100644 --- a/src/quantity/scalar/f64base.rs +++ b/src/quantity/scalar/f64base.rs @@ -8,8 +8,8 @@ use std::ops::{ use std::cmp::Ordering; use super::ScalarBase; -use super::SHOW_SIG; -use super::MAX_LEN; +use super::dec_to_sci; + macro_rules! foward { ( $x:ident ) => { @@ -27,87 +27,7 @@ pub struct F64Base where { impl ToString for F64Base { fn to_string(&self) -> String { - // Decimal, looks like xxx.xxx. - // May start with a zero. - let mut s = self.val.to_string(); - - // Remove negative sign from string - let neg = s.starts_with("-"); - if neg { s = String::from(&s[1..]); } - - // Power of ten - let mut p: i32 = { - if let Some(x) = s.find(".") { - x as i32 - } else { - s.len() as i32 - } - }; - p -= 1; - - // We no longer need a decimal point in our string. - // also, trim off leading zeros and adjust power. - let mut s: &str = &s.replace(".", ""); - s = &s[0..]; - s = s.trim_end_matches('0'); - while s.starts_with('0') { - s = &s[1..]; - p -= 1; - } - - - // Pick significant digits and round - let mut s = String::from(s); - if s.len() > SHOW_SIG { - let round; - if s.len() != SHOW_SIG + 1 { - round = s[SHOW_SIG..SHOW_SIG+1].parse().unwrap(); - } else { round = 0; } - - s = String::from(&s[0..SHOW_SIG]); - - if round >= 5 { - let new = s[s.len()-1..s.len()].parse::().unwrap() + 1u8; - if new != 10 { - s = format!("{}{new}", &s[0..s.len()-1]); - } - } - } - - s = format!("{s}{}", "0".repeat(SHOW_SIG - s.len())); - // at this point, s is guaranteed to have exactly SHOW_SIG digits. - - let neg = if neg {"-"} else {""}; - - if (p.abs() as usize) < MAX_LEN { - if p >= 0 { - let q = p as usize; - - let first = &s[0..q+1]; - let mut rest = &s[q+1..]; - rest = rest.trim_end_matches('0'); - if rest == "" { - return format!("{neg}{first}"); - } else { - return format!("{neg}{first}.{rest}"); - } - } else { - let q = p.abs() as usize; - let t = format!("0.{}{s}", "0".repeat(q-1)); - return format!("{neg}{}", t.trim_end_matches('0')); - } - - // Print full scientific notation - } else { - let first = &s[0..1]; - let mut rest = &s[1..]; - rest = rest.trim_end_matches('0'); - if rest == "" { - return format!("{neg}{first}e{p}"); - } else { - return format!("{neg}{first}.{rest}e{p}"); - } - } + return dec_to_sci(self.val.to_string()); } } diff --git a/src/quantity/scalar/floatbase.rs b/src/quantity/scalar/floatbase.rs index 84a37c9..77ce0d4 100644 --- a/src/quantity/scalar/floatbase.rs +++ b/src/quantity/scalar/floatbase.rs @@ -14,8 +14,8 @@ use std::ops::{ use std::cmp::Ordering; use super::ScalarBase; -use super::SHOW_SIG; -use super::MAX_LEN; +use super::dec_to_sci; + #[derive(Debug)] #[derive(Clone)] @@ -34,87 +34,7 @@ impl FloatBase { impl ToString for FloatBase { fn to_string(&self) -> String { - // Decimal, looks like xxx.xxx. - // May start with a zero. - let mut s = self.val.to_string(); - - // Remove negative sign from string - let neg = s.starts_with("-"); - if neg { s = String::from(&s[1..]); } - - // Power of ten - let mut p: i32 = { - if let Some(x) = s.find(".") { - x as i32 - } else { - s.len() as i32 - } - }; - p -= 1; - - // We no longer need a decimal point in our string. - // also, trim off leading zeros and adjust power. - let mut s: &str = &s.replace(".", ""); - s = &s[0..]; - s = s.trim_end_matches('0'); - while s.starts_with('0') { - s = &s[1..]; - p -= 1; - } - - - // Pick significant digits and round - let mut s = String::from(s); - if s.len() > SHOW_SIG { - let round; - if s.len() != SHOW_SIG + 1 { - round = s[SHOW_SIG..SHOW_SIG+1].parse().unwrap(); - } else { round = 0; } - - s = String::from(&s[0..SHOW_SIG]); - - if round >= 5 { - let new = s[s.len()-1..s.len()].parse::().unwrap() + 1u8; - if new != 10 { - s = format!("{}{new}", &s[0..s.len()-1]); - } - } - } - - s = format!("{s}{}", "0".repeat(SHOW_SIG - s.len())); - // at this point, s is guaranteed to have exactly SHOW_SIG digits. - - let neg = if neg {"-"} else {""}; - - if (p.abs() as usize) < MAX_LEN { - if p >= 0 { - let q = p as usize; - - let first = &s[0..q+1]; - let mut rest = &s[q+1..]; - rest = rest.trim_end_matches('0'); - if rest == "" { - return format!("{neg}{first}"); - } else { - return format!("{neg}{first}.{rest}"); - } - } else { - let q = p.abs() as usize; - let t = format!("0.{}{s}", "0".repeat(q-1)); - return format!("{neg}{}", t.trim_end_matches('0')); - } - - // Print full scientific notation - } else { - let first = &s[0..1]; - let mut rest = &s[1..]; - rest = rest.trim_end_matches('0'); - if rest == "" { - return format!("{neg}{first}e{p}"); - } else { - return format!("{neg}{first}.{rest}e{p}"); - } - } + return dec_to_sci(self.val.to_string()); } } diff --git a/src/quantity/scalar/mod.rs b/src/quantity/scalar/mod.rs index 8f8b8ed..7775380 100644 --- a/src/quantity/scalar/mod.rs +++ b/src/quantity/scalar/mod.rs @@ -18,4 +18,91 @@ pub use f64base::F64Base as FloatBase; mod scalar; pub use self::scalar::Scalar; -pub use self::scalar::ScalarBase; \ No newline at end of file +pub use self::scalar::ScalarBase; + + + +// Convert a string to scientific notation, +// with parameters SHOW_SIG and MAX_LEN. +// +// input (s): a decimal of any length, like 123123.123123 +// s may start with an optional `-` sign. +pub(in self) fn dec_to_sci(mut s: String) -> String { + // Remove negative sign from string + let neg = s.starts_with("-"); + if neg { s = String::from(&s[1..]); } + + // Power of ten + let mut p: i32 = { + if let Some(x) = s.find(".") { + x as i32 + } else { + s.len() as i32 + } + }; + p -= 1; + + // We no longer need a decimal point in our string. + // also, trim off leading zeros and adjust power. + let mut s: &str = &s.replace(".", ""); + s = &s[0..]; + s = s.trim_end_matches('0'); + while s.starts_with('0') { + s = &s[1..]; + p -= 1; + } + + + // Pick significant digits and round + let mut s = String::from(s); + if s.len() > SHOW_SIG { + let round; + if s.len() != SHOW_SIG + 1 { + round = s[SHOW_SIG..SHOW_SIG+1].parse().unwrap(); + } else { round = 0; } + + s = String::from(&s[0..SHOW_SIG]); + + if round >= 5 { + let new = s[s.len()-1..s.len()].parse::().unwrap() + 1u8; + if new != 10 { + s = format!("{}{new}", &s[0..s.len()-1]); + } + } + } + + s = format!("{s}{}", "0".repeat(SHOW_SIG - s.len())); + // at this point, s is guaranteed to have exactly SHOW_SIG digits. + + let neg = if neg {"-"} else {""}; + + if (p.abs() as usize) < MAX_LEN { + if p >= 0 { + let q = p as usize; + + let first = &s[0..q+1]; + let mut rest = &s[q+1..]; + rest = rest.trim_end_matches('0'); + if rest == "" { + return format!("{neg}{first}"); + } else { + return format!("{neg}{first}.{rest}"); + } + } else { + let q = p.abs() as usize; + let t = format!("0.{}{s}", "0".repeat(q-1)); + return format!("{neg}{}", t.trim_end_matches('0')); + } + + // Print full scientific notation + } else { + let first = &s[0..1]; + let mut rest = &s[1..]; + rest = rest.trim_end_matches('0'); + if rest == "" { + return format!("{neg}{first}e{p}"); + } else { + return format!("{neg}{first}.{rest}e{p}"); + } + } +} \ No newline at end of file