aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.rs')
-rw-r--r--src/eval.rs42
1 files changed, 32 insertions, 10 deletions
diff --git a/src/eval.rs b/src/eval.rs
index e07bec2..470bae6 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -194,19 +194,41 @@ impl Num {
}
}
-fn format_float(f: f64) -> String {
- let mut s = format!("{f:.7}");
- while let Some(b'0') = s.as_bytes().get(s.len() - 1) {
- s.truncate(s.len() - 1);
- }
- s
-}
-
impl Display for Num {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
- Num::Int(n) => write!(f, "{n}"),
- Num::Float(n) => write!(f, "{}", format_float(*n)),
+ Num::Int(n) => {
+ if n.bits() < 100 {
+ return write!(f, "{n}");
+ }
+ let buf = format!("{n}");
+ let rounding_factor = BigInt::from(10).pow(buf.len() - 8);
+ let (mut rounded, rem) = n.div_mod_floor(&rounding_factor);
+ match rem.cmp(&(rounding_factor / 2)) {
+ Ordering::Greater => rounded += 1,
+ Ordering::Equal if rounded.is_odd() => rounded += 1,
+ _ => (),
+ }
+ let rounded_str = format!("{rounded}");
+ write!(
+ f,
+ "{}.{}e{}",
+ &rounded_str[..1],
+ &rounded_str[1..],
+ buf.len() - 1
+ )
+ }
+ Num::Float(n) => {
+ let n = *n;
+ if !(-1e30..=1e30).contains(&n) {
+ return write!(f, "{n:.7e}");
+ }
+ let mut buf = format!("{n:.7}");
+ while let Some(b'0') = buf.as_bytes().get(buf.len() - 1) {
+ buf.truncate(buf.len() - 1);
+ }
+ write!(f, "{buf}")
+ }
}
}
}