java 计算中位数的实现方法

时间:2022-03-18 20:35:23

最近工作需要 要求把python的代码写成java版本,python中有一个np.median()求中位数的方法,java决定手写一个

说说什么是中位数:

中位数就是中间的那个数,

如果一个集合是奇数个,那么中位数就是按大小排列后,最中间那个数,

如果一个集合是偶数个,那么中位数就是按大小排列后,最中间那2个数的平均数。

比如:

1,2,3,4,5 那中位数就是3

1,2,3,4,5,6 那中位数就是 (3+4)/2 = 3.5

知道逻辑后方法就很简单了 下面是代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) {
 List<Integer> total = new ArrayList<Integer>();
 total.add(4);
 total.add(2);
 total.add(3);
 total.add(1);
 total.add(5);
 total.add(6);
 double a = median(total);
 System.out.println(a);
}
private static double median(List<Integer> total) {
 double j = 0;
 //集合排序
  Collections.sort(total);
  int size = total.size();
  if(size % 2 == 1){
   j = total.get((size-1)/2);
  }else {
   //加0.0是为了把int转成double类型,否则除以2会算错
   j = (total.get(size/2-1) + total.get(size/2) + 0.0)/2;
  }
 return j;
}

1. 方法内先判断集合是奇数还是偶数,如果是奇数那么就是第n+1/2个数 ,也就是下标为n-1/2的值,

如果是偶数 就是第n/2和n/2+1的数的平均值 也就是下标为n/2-1和n/2的平均值

2. 该方法传入的是list集合 如果为数组 可以先用Arrays.aslist()方法转换后传入

补充知识:Java计算中位数、方差、标准差、众数

我就废话不多说了,大家还是直接看代码吧~

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
import java.text.DecimalFormat;
import java.util.*;
 
/**
 * 数学算法(数学算法(方差、标准差、中位数、众数))
 * @author
 *
 */
public class MathAlgorithm {
    private final static double dmax = 999;// Double.MAX_VALUE;//Double类型的最大值,太大的double值,相乘会达到无穷大
    private final static double dmin = Double.MIN_VALUE;// Double类型的最小值
    private final static int n = 100;// 假设求取100个doubl数的方差和标准差
 
    public static void main(String[] args) {
        Random random = new Random();
        double[] x = new double[n];
        for (int i = 0; i < n; i++) {// 随机生成n个double数
            x[i] = Double.valueOf(Math.floor(random.nextDouble() * (dmax - dmin)));
            System.out.println(x[i]);
        }
        // 设置doubl字符串输出格式,不以科学计数法输出
        DecimalFormat df = new DecimalFormat("#,##0.00");// 格式化设置
        // 计算方差
        double dV = getVariance(x);
        System.out.println("方差=" + df.format(dV));
        // 计算标准差
        double dS = getStandardDiviation(x);
        System.out.println("标准差=" + df.format(dS));
        
        
        int[] intArr={5,10,15,8,6};
        System.out.println(Arrays.toString(intArr)+" 中位数:"+median(intArr));
        
        int[] intArr2={5,10,15,8,6,7};
        System.out.println(Arrays.toString(intArr2)+" 中位数:"+median(intArr2));
        
        int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 2, 2, 3, 4, 5};
 
    List<Integer> modalNums = getModalNums(arr);
    System.out.println("众数:"+modalNums);
    
    float[] arr2 = {0.1f, 1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1f, 8.1f, 9.1f, 10.1f, 1.1f, 1.1f, 2.1f, 2.1f, 3.1f, 4.1f, 5.1f};
 
    List<Float> modalNums2 = getModalNums(arr2);
 
    System.out.println("众数:"+modalNums2);
    }
 
    /**
     * 方差s^2=[(x1-x)^2 +...(xn-x)^2]/n
     * @param x
     * @return
     */
    public static double getVariance(double[] x) {
        int m = x.length;
        double sum = 0;
        for (int i = 0; i < m; i++) {// 求和
            sum += x[i];
        }
        double dAve = sum / m;// 求平均值
        double dVar = 0;
        for (int i = 0; i < m; i++) {// 求方差
            dVar += (x[i] - dAve) * (x[i] - dAve);
        }
        return dVar / m;
    }
 
    /**
     * 标准差σ=sqrt(s^2)
     * @param x
     * @return
     */
    public static double getStandardDiviation(double[] x) {
        int m = x.length;
        double sum = 0;
        for (int i = 0; i < m; i++) {// 求和
            sum += x[i];
        }
        double dAve = sum / m;// 求平均值
        double dVar = 0;
        for (int i = 0; i < m; i++) {// 求方差
            dVar += (x[i] - dAve) * (x[i] - dAve);
        }
        return Math.sqrt(dVar / m);
    }
    
    /**
     * 中位数(int)
   * @param nums: A list of integers.
   * @return: An integer denotes the middle number of the array.
   */
  public static int median(int []nums){
        if(nums.length==0)
            return 0;
        int start=0;
        int end=nums.length-1;
        int index=partition(nums, start, end);
        if(nums.length%2==0){
            while(index!=nums.length/2-1){
                if(index>nums.length/2-1){
                    index=partition(nums, start, index-1);
                }else{
                    index=partition(nums, index+1, end);
                }
            }
        }else{
            while(index!=nums.length/2){
                if(index>nums.length/2){
                    index=partition(nums, start, index-1);
                }else{
                    index=partition(nums, index+1, end);
                }
            }
        }
        return nums[index];
    }
  
    private static int partition(int nums[], int start, int end){
        int left=start;
        int right=end;
        int pivot=nums[left];
        while(left<right){
            while(left<right&&nums[right]>=pivot){
                right--;
            }
            if(left<right){
                nums[left]=nums[right];
                left++;
            }
            while(left<right&&nums[left]<=pivot){
                left++;
            }
            if(left<right){
                nums[right]=nums[left];
                right--;
            }
        }
        nums[left]=pivot;
        return left;
    }
    
    /**
     * 中位数(float)
   * @param nums: A list of integers.
   * @return: An integer denotes the middle number of the array.
   */
  public static float median(float []nums){
        if(nums.length==0)
            return 0;
        int start=0;
        int end=nums.length-1;
        int index=partition(nums, start, end);
        if(nums.length%2==0){
            while(index!=nums.length/2-1){
                if(index>nums.length/2-1){
                    index=partition(nums, start, index-1);
                }else{
                    index=partition(nums, index+1, end);
                }
            }
        }else{
            while(index!=nums.length/2){
                if(index>nums.length/2){
                    index=partition(nums, start, index-1);
                }else{
                    index=partition(nums, index+1, end);
                }
            }
        }
        return nums[index];
    }
  
    private static int partition(float nums[], int start, int end){
        int left=start;
        int right=end;
        float pivot=nums[left];
        while(left<right){
            while(left<right&&nums[right]>=pivot){
                right--;
            }
            if(left<right){
                nums[left]=nums[right];
                left++;
            }
            while(left<right&&nums[left]<=pivot){
                left++;
            }
            if(left<right){
                nums[right]=nums[left];
                right--;
            }
        }
        nums[left]=pivot;
        return left;
    }
    
    /**
     * 众数(int)
     * 众数:在一个数组中出现次数最多的数
     * 如果存在多个众数,则一起返回
     * @param arr
     * @return
     */
    public static List<Integer> getModalNums(int[] arr) {
    int n = arr.length;
 
    if (n == 0) {
      return new ArrayList<Integer>();
    }
 
    if (n == 1) {
      return Arrays.asList(arr[0]);
    }
 
    Map<Integer, Integer> freqMap = new HashMap<>();
    for (int i = 0; i < n; i++) { // 统计数组中每个数出现的频率
      Integer v = freqMap.get(arr[i]);
      // v == null 说明 freqMap 中还没有这个 arr[i] 这个键
      freqMap.put(arr[i], v == null ? 1 : v + 1);
    }
 
    // 将 freqMap 中所有的键值对(键为数,值为数出现的频率)放入一个 ArrayList
    List<Map.Entry<Integer, Integer>> entries = new ArrayList<>(freqMap.entrySet());
    // 对 entries 按出现频率从大到小排序
    Collections.sort(entries, new Comparator<Map.Entry<Integer, Integer>>() {
      @Override
      public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) {
        return e2.getValue() - e1.getValue();
      }
    });
 
    List<Integer> modalNums = new ArrayList<>();
    modalNums.add(entries.get(0).getKey()); // 排序后第一个 entry 的键肯定是一个众数
 
    int size = entries.size();
    for (int i = 1; i < size; i++) {
      // 如果之后的 entry 与第一个 entry 的 value 相等,那么这个 entry 的键也是众数
      if (entries.get(i).getValue().equals(entries.get(0).getValue())) {
        modalNums.add(entries.get(i).getKey());
      } else {
        break;
      }
    }
 
    return modalNums;
  }
    
    /**
     * 众数(float)
     * 众数:在一个数组中出现次数最多的数
     * 如果存在多个众数,则一起返回
     * @param arr
     * @return
     */
    public static List<Float> getModalNums(float[] arr) {
    int n = arr.length;
 
    if (n == 0) {
      return new ArrayList<Float>();
    }
 
    if (n == 1) {
      return Arrays.asList(arr[0]);
    }
 
    Map<Float, Integer> freqMap = new HashMap<>();
    for (int i = 0; i < n; i++) { // 统计数组中每个数出现的频率
      Integer v = freqMap.get(arr[i]);
      // v == null 说明 freqMap 中还没有这个 arr[i] 这个键
      freqMap.put(arr[i], v == null ? 1 : v + 1);
    }
 
    // 将 freqMap 中所有的键值对(键为数,值为数出现的频率)放入一个 ArrayList
    List<Map.Entry<Float, Integer>> entries = new ArrayList<>(freqMap.entrySet());
    // 对 entries 按出现频率从大到小排序
    Collections.sort(entries, new Comparator<Map.Entry<Float, Integer>>() {
      @Override
      public int compare(Map.Entry<Float, Integer> e1, Map.Entry<Float, Integer> e2) {
        return e2.getValue() - e1.getValue();
      }
    });
 
    List<Float> modalNums = new ArrayList<>();
    modalNums.add(entries.get(0).getKey()); // 排序后第一个 entry 的键肯定是一个众数
 
    int size = entries.size();
    for (int i = 1; i < size; i++) {
      // 如果之后的 entry 与第一个 entry 的 value 相等,那么这个 entry 的键也是众数
      if (entries.get(i).getValue().equals(entries.get(0).getValue())) {
        modalNums.add(entries.get(i).getKey());
      } else {
        break;
      }
    }
 
    return modalNums;
  }
}

以上这篇java 计算中位数的实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/zhang_z_ming/article/details/85779901