[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 {
|
||||
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!
|
||||
text
|
||||
} else {
|
||||
|
@ -96,3 +97,52 @@ pub fn format_with_minimum_precision(value: f32, precision: usize) -> 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