numeric_statistics/f64/
variance.rs1use super::average;
2
3pub fn variance<T: AsRef<[f64]>>(values: T) -> f64 {
10 let values = values.as_ref();
11 if values.is_empty() { return f64::NAN; }
12 let average = average(values);
13 variance_with_average(values, average)
14}
15
16pub fn variance_with_average<T: AsRef<[f64]>>(values: T, average: f64) -> f64 {
24 let values = values.as_ref();
25 if values.is_empty() { return f64::NAN; }
26 let mut delta_square_sum: f64 = 0.0;
27 let mut len: usize = 0;
28 values.iter().for_each(|x|
29 if !x.is_nan() {
30 let delta = *x - average;
31 delta_square_sum += delta * delta;
32 len += 1;
33 }
34 );
35 match len {
36 0 => return f64::NAN,
37 1 => return 0.0,
38 x => delta_square_sum / (x - 1) as f64
39 }
40}
41
42#[cfg(test)]
43mod test {
44 use super::*;
45
46 #[test]
47 fn test_empty() {
48 let x: &[f64] = &[];
49 assert!(variance(x).is_nan());
50 }
51
52 #[test]
53 fn test_nan() {
54 let x: &[f64] = &[f64::NAN];
55 assert!(variance(x).is_nan());
56 }
57
58 #[test]
59 fn test_value() {
60 let x: &[f64] = &[1.0];
61 assert_eq_float!(variance(x), 0.0);
62 }
63
64 #[test]
65 fn test_values_ascending() {
66 let x = &[1.0, 2.0, 4.0];
67 assert_eq_float!(variance(x), 2.3333333333333333);
68 }
69
70 #[test]
71 fn test_values_ascending_and_nans() {
72 let x = &[1.0, f64::NAN, 2.0, f64::NAN, 4.0];
73 assert_eq_float!(variance(x), 2.3333333333333333);
74 }
75
76}