pub(crate) fn python_round(value: f64, digits: usize) -> f64 {
format!("{value:.digits$}").parse::<f64>().unwrap_or(value)
}
#[cfg(test)]
mod tests {
use super::python_round;
#[test]
fn tie_cases_match_cpython() {
assert_eq!(python_round(0.0625, 3).to_bits(), 0.062_f64.to_bits());
assert_eq!(python_round(2.675, 2).to_bits(), 2.67_f64.to_bits());
assert_eq!(python_round(0.25, 1).to_bits(), 0.2_f64.to_bits());
assert_eq!(python_round(0.75, 1).to_bits(), 0.8_f64.to_bits());
assert_eq!(python_round(0.000_05, 4).to_bits(), 0.0001_f64.to_bits());
}
#[test]
fn negative_zero_is_preserved() {
let rounded = python_round(-0.000_04, 3);
assert_eq!(rounded.to_bits(), (-0.0_f64).to_bits());
}
#[test]
fn passthrough_of_representable_values() {
assert_eq!(python_round(0.4404, 4).to_bits(), 0.4404_f64.to_bits());
assert_eq!(python_round(-0.6597, 4).to_bits(), (-0.6597_f64).to_bits());
assert_eq!(python_round(0.0, 4).to_bits(), 0.0_f64.to_bits());
assert_eq!(python_round(1.0, 4).to_bits(), 1.0_f64.to_bits());
assert_eq!(python_round(-1.0, 4).to_bits(), (-1.0_f64).to_bits());
}
}