Cleaned up to_string functions

newfloat
Mark 2023-09-03 16:03:24 -07:00
parent 47abd9d18e
commit b9cfe719a6
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
3 changed files with 94 additions and 167 deletions

View File

@ -8,8 +8,8 @@ use std::ops::{
use std::cmp::Ordering; use std::cmp::Ordering;
use super::ScalarBase; use super::ScalarBase;
use super::SHOW_SIG; use super::dec_to_sci;
use super::MAX_LEN;
macro_rules! foward { macro_rules! foward {
( $x:ident ) => { ( $x:ident ) => {
@ -27,87 +27,7 @@ pub struct F64Base where {
impl ToString for F64Base { impl ToString for F64Base {
fn to_string(&self) -> String { fn to_string(&self) -> String {
// Decimal, looks like xxx.xxx. return dec_to_sci(self.val.to_string());
// 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::<u8>().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}");
}
}
} }
} }

View File

@ -14,8 +14,8 @@ use std::ops::{
use std::cmp::Ordering; use std::cmp::Ordering;
use super::ScalarBase; use super::ScalarBase;
use super::SHOW_SIG; use super::dec_to_sci;
use super::MAX_LEN;
#[derive(Debug)] #[derive(Debug)]
#[derive(Clone)] #[derive(Clone)]
@ -34,87 +34,7 @@ impl FloatBase {
impl ToString for FloatBase { impl ToString for FloatBase {
fn to_string(&self) -> String { fn to_string(&self) -> String {
// Decimal, looks like xxx.xxx. return dec_to_sci(self.val.to_string());
// 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::<u8>().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}");
}
}
} }
} }

View File

@ -19,3 +19,90 @@ pub use f64base::F64Base as FloatBase;
mod scalar; mod scalar;
pub use self::scalar::Scalar; pub use self::scalar::Scalar;
pub use self::scalar::ScalarBase; 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::<u8>().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}");
}
}
}