[slider] only show full precision if significant
This commit is contained in:
parent
cc22e2fbb4
commit
b3b4fbc016
1 changed files with 51 additions and 1 deletions
|
@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue