pub fn java_format_double(v: f64) -> String {
if v.is_nan() {
return "NaN".to_string();
}
if v.is_infinite() {
return if v.is_sign_positive() {
"Infinity".to_string()
} else {
"-Infinity".to_string()
};
}
if v == 0.0 && v.is_sign_negative() {
return "-0.0".to_string();
}
let abs = v.abs();
if abs != 0.0 && !(1e-3..1e7).contains(&abs) {
return format_scientific(v);
}
let s = format!("{}", v);
if s.contains('.') {
s
} else {
format!("{}.0", s)
}
}
fn format_scientific(v: f64) -> String {
let s = format!("{:e}", v);
let s = s.replace('e', "E");
if let Some(e_pos) = s.find('E') {
let (mantissa, exp_part) = s.split_at(e_pos);
let exp_str = &exp_part[1..];
let mantissa = if mantissa.contains('.') {
mantissa.to_string()
} else {
format!("{}.0", mantissa)
};
if let Ok(exp_val) = exp_str.parse::<i32>() {
return format!("{}E{}", mantissa, exp_val);
}
}
s
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_integer_values() {
assert_eq!(java_format_double(9.0), "9.0");
assert_eq!(java_format_double(100.0), "100.0");
assert_eq!(java_format_double(0.0), "0.0");
assert_eq!(java_format_double(1.0), "1.0");
assert_eq!(java_format_double(5.0), "5.0");
assert_eq!(java_format_double(20.0), "20.0");
}
#[test]
fn test_fractional_values() {
assert_eq!(java_format_double(0.5), "0.5");
assert_eq!(java_format_double(2.5), "2.5");
}
#[test]
fn test_nan() {
assert_eq!(java_format_double(f64::NAN), "NaN");
}
#[test]
fn test_infinity() {
assert_eq!(java_format_double(f64::INFINITY), "Infinity");
assert_eq!(java_format_double(f64::NEG_INFINITY), "-Infinity");
}
#[test]
fn test_negative_zero() {
assert_eq!(java_format_double(-0.0), "-0.0");
}
#[test]
fn test_negative_values() {
assert_eq!(java_format_double(-1.0), "-1.0");
assert_eq!(java_format_double(-0.5), "-0.5");
}
#[test]
fn test_scientific_large() {
assert_eq!(java_format_double(1e7), "1.0E7");
assert_eq!(java_format_double(1.5e10), "1.5E10");
}
#[test]
fn test_scientific_small() {
assert_eq!(java_format_double(1e-4), "1.0E-4");
assert_eq!(java_format_double(1.5e-4), "1.5E-4");
}
#[test]
fn test_normal_range_boundary() {
assert_eq!(java_format_double(0.001), "0.001");
assert_eq!(java_format_double(9999999.0), "9999999.0");
}
#[test]
fn test_typical_fastqc_doubles() {
assert_eq!(java_format_double(25.0), "25.0");
assert_eq!(java_format_double(50.0), "50.0");
assert_eq!(java_format_double(75.0), "75.0");
assert_eq!(java_format_double(12.345), "12.345");
assert_eq!(java_format_double(99.99), "99.99");
}
#[test]
fn test_very_precise_decimal() {
let val = 33.333333333333336;
let formatted = java_format_double(val);
assert!(formatted.contains('.'));
let parsed: f64 = formatted.parse().unwrap();
assert_eq!(parsed, val);
}
}