From 38dc8649fab2e8e2608e75facc7a104cb4adf985 Mon Sep 17 00:00:00 2001 From: Aras14HD Date: Tue, 24 Feb 2026 20:11:46 +0100 Subject: [PATCH] add formatting of small floats (10^-n) also fixes incorrect rounding --- Cargo.lock | 6 +- factorion-bot-discord/Cargo.toml | 4 +- factorion-bot-reddit/Cargo.toml | 4 +- factorion-lib/Cargo.toml | 2 +- factorion-lib/src/calculation_results.rs | 80 +++++++++++++++++++++--- factorion-lib/src/parse.rs | 4 -- 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32d72f95..4b48d1a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,7 +399,7 @@ dependencies = [ [[package]] name = "factorion-bot-discord" -version = "2.1.13" +version = "2.2.0" dependencies = [ "anyhow", "dotenvy", @@ -414,7 +414,7 @@ dependencies = [ [[package]] name = "factorion-bot-reddit" -version = "5.2.13" +version = "5.2.0" dependencies = [ "anyhow", "base64 0.22.1", @@ -434,7 +434,7 @@ dependencies = [ [[package]] name = "factorion-lib" -version = "4.1.12" +version = "4.2.0" dependencies = [ "arbtest", "chrono", diff --git a/factorion-bot-discord/Cargo.toml b/factorion-bot-discord/Cargo.toml index 52030a15..24688800 100644 --- a/factorion-bot-discord/Cargo.toml +++ b/factorion-bot-discord/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "factorion-bot-discord" -version = "2.1.13" +version = "2.2.0" edition = "2024" description = "factorion-bot (for factorials and related) on Discord" license = "MIT" @@ -10,7 +10,7 @@ keywords = ["factorial", "termial", "bot", "math", "discord"] categories = ["mathematics", "web-programming", "parser-implementations"] [dependencies] -factorion-lib = { path = "../factorion-lib", version = "4.1.12", features = ["serde", "influxdb"] } +factorion-lib = { path = "../factorion-lib", version = "4.2.0", features = ["serde", "influxdb"] } serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] } tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread", "time"] } dotenvy = "^0.15.7" diff --git a/factorion-bot-reddit/Cargo.toml b/factorion-bot-reddit/Cargo.toml index a0c7ad8f..482b8e61 100644 --- a/factorion-bot-reddit/Cargo.toml +++ b/factorion-bot-reddit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "factorion-bot-reddit" -version = "5.2.13" +version = "5.2.0" edition = "2024" description = "factorion-bot (for factorials and related) on Reddit" license = "MIT" @@ -10,7 +10,7 @@ keywords = ["factorial", "termial", "bot", "math"] categories = ["mathematics", "web-programming", "parser-implementations"] [dependencies] -factorion-lib = {path = "../factorion-lib", version = "4.1.12", features = ["serde", "influxdb"]} +factorion-lib = {path = "../factorion-lib", version = "4.2.0", features = ["serde", "influxdb"]} reqwest = { version = "0.12.28", features = ["json", "native-tls"], default-features = false } serde = { version = "1.0.219", default-features = false, features = ["derive"] } serde_json = "1.0.140" diff --git a/factorion-lib/Cargo.toml b/factorion-lib/Cargo.toml index c13c534c..551e241a 100644 --- a/factorion-lib/Cargo.toml +++ b/factorion-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "factorion-lib" -version = "4.1.12" +version = "4.2.0" edition = "2024" description = "A library used to create bots to recognize and calculate factorials and related concepts" license = "MIT" diff --git a/factorion-lib/src/calculation_results.rs b/factorion-lib/src/calculation_results.rs index 85ee49c7..9aa53f02 100644 --- a/factorion-lib/src/calculation_results.rs +++ b/factorion-lib/src/calculation_results.rs @@ -493,9 +493,11 @@ impl Calculation { /// If the input is all 9s, this will round to 10. \ /// Stops when a decimal period is encountered, removing it. /// +/// Returns whether it overflowed. +/// /// # Panic /// This function may panic if less than two digits are supplied, or if it contains a non-digit of base 10, that is not a period. -fn round(number: &mut String) { +fn round(number: &mut String) -> bool { // Check additional digit if we need to round if let Some(digit) = number .pop() @@ -511,7 +513,7 @@ fn round(number: &mut String) { let Some(digit) = number.pop() else { // If we reached the end we get 10 number.push_str("10"); - return; + return true; }; // Stop at decimal if digit == '.' { @@ -523,6 +525,7 @@ fn round(number: &mut String) { // Round up let _ = write!(number, "{}", last_digit + 1); } + false } fn truncate(number: &Integer, consts: &Consts) -> (String, bool) { let prec = consts.float_precision; @@ -576,17 +579,21 @@ fn format_float(acc: &mut String, number: &Float, consts: &Consts) -> std::fmt:: let mut number = number.clone(); let negative = number.is_sign_negative(); number = number.abs(); + if number == 0 { + return acc.write_char('0'); + } let exponent = number .clone() .log10() - .max(&Float::new(consts.float_precision)) .to_integer_round(factorion_math::rug::float::Round::Down) .expect("Could not round exponent") .0; - if exponent > consts.number_decimals_scientific { + if exponent > consts.number_decimals_scientific + || exponent < -(consts.number_decimals_scientific as isize) + { number = number / Float::with_val(consts.float_precision, &exponent).exp10(); } - let whole_number = number + let mut whole_number = number .to_integer_round(factorion_math::rug::float::Round::Down) .expect("Could not get integer part") .0; @@ -597,7 +604,10 @@ fn format_float(acc: &mut String, number: &Float, consts: &Consts) -> std::fmt:: decimal_part.remove(0); decimal_part.truncate(consts.number_decimals_scientific + 1); if decimal_part.len() > consts.number_decimals_scientific { - round(&mut decimal_part); + if round(&mut decimal_part) { + decimal_part.clear(); + whole_number += 1; + } } if let Some(mut digit) = decimal_part.pop() { while digit == '0' { @@ -616,7 +626,9 @@ fn format_float(acc: &mut String, number: &Float, consts: &Consts) -> std::fmt:: acc.write_str(".")?; acc.write_str(&decimal_part)?; } - if exponent > consts.number_decimals_scientific { + if exponent > consts.number_decimals_scientific + || exponent < -(consts.number_decimals_scientific as isize) + { write!(acc, " × 10^{exponent}")?; } Ok(()) @@ -1497,4 +1509,58 @@ mod test { .unwrap(); assert_eq!(acc, "4.9814983749234732849839849898438493843 × 10^(1037)"); } + #[test] + fn test_format_float() { + let mut consts = Consts::default(); + let mut acc = String::new(); + format_float( + &mut acc, + &Float::with_val( + FLOAT_PRECISION, + Float::parse("0.999999999999999999999999999999999").unwrap(), + ), + &consts, + ) + .unwrap(); + assert_eq!(acc, "1"); + let mut acc = String::new(); + format_float( + &mut acc, + &Float::with_val( + FLOAT_PRECISION, + Float::parse("0.000000000000000000000000000000009").unwrap(), + ), + &consts, + ) + .unwrap(); + assert_eq!(acc, "9 × 10^-33"); + consts.number_decimals_scientific = 2; + acc.clear(); + format_float( + &mut acc, + &Float::with_val(FLOAT_PRECISION, Float::parse("0.10").unwrap()), + &consts, + ) + .unwrap(); + assert_eq!(acc, "0.1"); + + let consts = Consts::default(); + acc.clear(); + format_float( + &mut acc, + &Float::with_val(FLOAT_PRECISION, Float::parse("6.631537423e-34").unwrap()), + &consts, + ) + .unwrap(); + assert_eq!(acc, "6.631537423 × 10^-34"); + let consts = Consts::default(); + acc.clear(); + format_float( + &mut acc, + &Float::with_val(FLOAT_PRECISION, Float::parse("6.631537423e34").unwrap()), + &consts, + ) + .unwrap(); + assert_eq!(acc, "6.631537423 × 10^34"); + } } diff --git a/factorion-lib/src/parse.rs b/factorion-lib/src/parse.rs index 30a63a55..168ac253 100644 --- a/factorion-lib/src/parse.rs +++ b/factorion-lib/src/parse.rs @@ -1484,10 +1484,6 @@ mod test { &consts, &NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }), ); - assert_eq!( - num, - Some(Number::Float(Float::with_val(FLOAT_PRECISION, 0.5).into())) - ); let num = parse_num( &mut "1more !", false,