Skip to main content

cts_math/
statistic.rs

1use std::{cmp::Ordering, ops::AddAssign};
2use num::{Float, NumCast};
3
4/// 计算数据的格式
5pub fn count<T>(data: &[T]) -> usize {
6    data.iter().count()
7}
8
9/// 计算数组的最小值
10pub fn min<T>(data: &[T]) -> Option<T>
11where
12    T: PartialOrd + Copy,
13{
14    if data.is_empty() {
15        return None;
16    }
17
18    let mut min_result = data[0];
19
20    for &item in data.iter().skip(1) {
21        if min_result > item {
22            min_result = item;
23        }
24    }
25
26    Some(min_result)
27}
28
29
30/// 计算数组的最大值
31pub fn max<T>(data: &[T]) -> Option<T>
32where
33    T: PartialOrd + Copy,
34{
35    if data.is_empty() {
36        return None;
37    }
38
39    let mut max_result = data[0];
40
41    for &item in data.iter().skip(1) {
42        if max_result < item {
43            max_result = item;
44        }
45    }
46
47    Some(max_result)
48}
49
50/// 计算数组的平均值
51pub fn avg<T>(data: &[T]) -> Option<f64>
52where
53    T: std::convert::Into<f64> + Copy,
54{
55    if data.is_empty() {
56        return None;
57    }
58
59    let mut result = 0.0;
60    let mut count = 0;
61
62    for &item in data {
63        let value: f64 = item.into();
64        result += value;
65        count += 1;
66    }
67
68    Some(result / count as f64)
69}
70
71/// 计算数组的中位数
72pub fn median<T>(numbers: &[T]) -> Option<T>
73where
74    T: PartialOrd + Clone,
75{
76    if numbers.is_empty() {
77        return None;
78    }
79
80    let len = numbers.len();
81    let mid = len / 2;
82
83    // 如果只有一个元素,直接返回
84    if len == 1 {
85        return Some(numbers[0].clone());
86    }
87
88    // 创建可变副本进行排序
89    let mut sorted_numbers = numbers.to_vec();
90    sorted_numbers.sort_by(|a, b| {
91        a.partial_cmp(b).unwrap_or_else(|| {
92            // 处理无法比较的情况,这里我们选择保持顺序
93            Ordering::Equal
94        })
95    });
96
97    if len % 2 == 0 {
98        // 偶数个元素,取中间两个数的平均值
99        // 注意:这里需要 T 支持加法和除法
100        // 如果 T 不支持这些运算,可能需要不同的实现
101        Some(sorted_numbers[mid - 1].clone())
102    } else {
103        // 奇数个元素,取中间的数
104        Some(sorted_numbers[mid].clone())
105    }
106}
107
108///计算数组的标准差
109pub fn std_dev<T, U>(data: &[T]) -> U
110where
111    T: NumCast + Copy,
112    U: Float + AddAssign + NumCast,
113{
114    if data.len() < 2 {
115        return U::zero();
116    }
117
118    let n = U::from(data.len()).unwrap();
119    let n_minus_one = U::from(data.len() - 1).unwrap();
120
121    // 使用 fold 计算总和
122    let sum = data.iter()
123        .map(|&x| U::from(x).unwrap())
124        .fold(U::zero(), |acc, x| acc + x);
125
126    let mean = sum / n;
127
128    // 使用 fold 计算方差
129    let variance = data.iter()
130        .map(|&x| {
131            let val = U::from(x).unwrap();
132            let diff = val - mean;
133            diff * diff
134        })
135        .fold(U::zero(), |acc, x| acc + x) / n_minus_one;
136
137    variance.sqrt()
138}