/// Formats `f64` with Java `Double.toString` semantics as closely as Rust's /// shortest-roundtrip formatting allows. pub fn format_java_double(value: f64) -> String { if value.is_nan() { return "NaN".to_string(); } if value == f64::INFINITY { return "Infinity".to_string(); } if value == f64::NEG_INFINITY { return "-Infinity".to_string(); } if value == 0.0 { return if value.is_sign_negative() { "-0.0".to_string() } else { "0.0".to_string() }; } let scientific = format!("{value:e}"); let (mantissa, exp) = scientific .split_once('e') .expect("lowerexp formatting always contains e"); let exponent: i32 = exp.parse().expect("lowerexp exponent is an integer"); let negative = mantissa.starts_with('-'); let mantissa = mantissa.trim_start_matches('-'); let digits: String = mantissa.chars().filter(|c| *c != '.').collect(); // Java uses plain decimal notation for 1e-3 <= abs(value) < 1e7. if (-3..7).contains(&exponent) { let point_pos = exponent + 1; let mut out = String::new(); if negative { out.push('-'); } if point_pos <= 0 { out.push_str("0."); for _ in 0..(-point_pos) { out.push('0'); } out.push_str(&digits); } else if point_pos as usize >= digits.len() { out.push_str(&digits); for _ in 0..(point_pos as usize - digits.len()) { out.push('0'); } out.push_str(".0"); } else { let split = point_pos as usize; out.push_str(&digits[..split]); out.push('.'); out.push_str(&digits[split..]); } out } else { let mut out = String::new(); if negative { out.push('-'); } out.push(digits.as_bytes()[0] as char); out.push('.'); if digits.len() == 1 { out.push('0'); } else { out.push_str(&digits[1..]); } out.push('E'); out.push_str(&exponent.to_string()); out } } #[cfg(test)] mod tests { use super::format_java_double; #[test] fn java_double_formatting() { assert_eq!(format_java_double(1.0), "1.0"); assert_eq!(format_java_double(36.0), "36.0"); assert_eq!(format_java_double(0.001), "0.001"); assert_eq!(format_java_double(0.0001), "1.0E-4"); assert_eq!(format_java_double(9_999_999.0), "9999999.0"); assert_eq!(format_java_double(10_000_000.0), "1.0E7"); assert_eq!(format_java_double(1e22), "1.0E22"); assert_eq!(format_java_double(1e-7), "1.0E-7"); assert_eq!(format_java_double(-2.5), "-2.5"); } }