[slider] only show full precision if significant

This commit is contained in:
Emil Ernerfeldt 2020-08-29 14:41:32 +02:00
parent cc22e2fbb4
commit b3b4fbc016

View file

@ -86,7 +86,8 @@ pub fn round_to_precision(value: f32, decimal_places: usize) -> f32 {
pub fn format_with_minimum_precision(value: f32, precision: usize) -> String { pub fn format_with_minimum_precision(value: f32, precision: usize) -> String {
let text = format!("{:.*}", precision, value); let text = format!("{:.*}", precision, value);
if (text.parse::<f32>().unwrap() - value).abs() <= std::f32::EPSILON { let epsilon = 16.0 * f32::EPSILON; // margin large enough to handle most peoples round-tripping needs
if almost_equal(text.parse::<f32>().unwrap(), value, epsilon) {
// Enough precision to show the value accurately - good! // Enough precision to show the value accurately - good!
text text
} else { } else {
@ -96,3 +97,52 @@ pub fn format_with_minimum_precision(value: f32, precision: usize) -> String {
value.to_string() value.to_string()
} }
} }
/// Should return true when arguments are the same within some rounding error.
/// For instance `almost_equal(x, x.to_degrees().to_radians(), f32::EPSILON)` should hold true for all x.
/// The `epsilon` can be `f32::EPSILON` to handle simple transforms (like degrees -> radians)
/// but should be higher to handle more complex transformations.
pub fn almost_equal(a: f32, b: f32, epsilon: f32) -> bool {
#![allow(clippy::float_cmp)]
if a == b {
true // handle infinites
} else {
let abs_max = a.abs().max(b.abs());
abs_max <= epsilon || ((a - b).abs() / abs_max) <= epsilon
}
}
#[test]
fn test_almost_equal() {
for &x in &[
0.0_f32,
f32::MIN_POSITIVE,
1e-20,
1e-10,
f32::EPSILON,
0.1,
0.99,
1.0,
1.001,
1e10,
f32::MAX / 100.0,
// f32::MAX, // overflows in rad<->deg test
f32::INFINITY,
] {
for &x in &[-x, x] {
for roundtrip in &[
|x: f32| x.to_degrees().to_radians(),
|x: f32| x.to_radians().to_degrees(),
] {
let epsilon = f32::EPSILON;
assert!(
almost_equal(x, roundtrip(x), epsilon),
"{} vs {}",
x,
roundtrip(x)
);
}
}
}
}