PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/racetrack/util/QuickStats.java

https://bitbucket.org/dcode/racetrack
Java | 245 lines | 101 code | 34 blank | 110 comment | 50 complexity | 4887949fe2dbc5fdb8b8423913f15fd0 MD5 | raw file
  1. /*
  2. Copyright 2017 David Trimm
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package racetrack.util;
  14. import java.util.Arrays;
  15. import java.util.List;
  16. /**
  17. * Class for calculating quick statistics on an array or List of integers, floats, or doubles.
  18. */
  19. public class QuickStats {
  20. /**
  21. * Minimum value of the samples
  22. */
  23. double min_value = Double.POSITIVE_INFINITY;
  24. /**
  25. * Maximum value of the samples
  26. */
  27. double max_value = Double.NEGATIVE_INFINITY;
  28. /**
  29. * Median value of the samples
  30. */
  31. double median_value = Double.NaN;
  32. /**
  33. * Standard deviation value
  34. */
  35. double stdev_value = Double.NaN;
  36. /**
  37. * Sum of the samples
  38. */
  39. double sum = 0.0;
  40. /**
  41. * Total number of samples
  42. */
  43. int samples = 0;
  44. /**
  45. * Construct the class by calculating all quick stats variables.
  46. *
  47. *@param ints list of integers -- converted over to an array for processing
  48. */
  49. public QuickStats(List<Integer> ints) {
  50. int as_array[] = new int[ints.size()];
  51. for (int i=0;i<as_array.length;i++) as_array[i] = ints.get(i);
  52. constructWithIntegerArray(as_array);
  53. }
  54. /**
  55. * Construct the class by calculating all quick stats variables.
  56. *
  57. *@param ints integer values in array
  58. */
  59. public QuickStats(int ints[]) { constructWithIntegerArray(ints); }
  60. /**
  61. * Null constructor for subclasses
  62. */
  63. protected QuickStats() { }
  64. /**
  65. * Copy of my_ints
  66. */
  67. int my_ints[];
  68. /**
  69. * Generic constructor based on array of integers.
  70. *
  71. *@param ints integer values in array
  72. */
  73. private void constructWithIntegerArray(int ints[]) {
  74. my_ints = ints;
  75. // Min, max, and sum/average
  76. for (int i=0;i<ints.length;i++) {
  77. sum += ints[i]; samples++;
  78. if (ints[i] < min_value) min_value = ints[i];
  79. if (ints[i] > max_value) max_value = ints[i];
  80. }
  81. }
  82. /**
  83. *
  84. */
  85. protected int qSortMedian(int ints[]) {
  86. // System.out.println(); System.out.println();
  87. int i0 = 0, i1 = ints.length-1;
  88. while (true) {
  89. int l = i1 - i0 + 1;
  90. if (l == 1) { return ints[ints.length/2];
  91. } else if (l == 2) { if (ints[i0] > ints[i1]) { swap(ints,i0, i1); } return ints[ints.length/2];
  92. } else if (l == 3) { if (ints[i0] > ints[i0+1]) { swap(ints,i0, i0+1); }
  93. if (ints[i0+1] > ints[i0+2]) { swap(ints,i0+1,i0+2); }
  94. if (ints[i0] > ints[i0+1]) { swap(ints,i0, i0+1); }
  95. return ints[ints.length/2];
  96. } else {
  97. // pick the best of three for a pivot point
  98. int s[] = new int[3]; int in[] = new int[3]; s[0] = ints[i0]; in[0] = i0; s[1] = ints[(i0+i1)/2]; in[1] = (i0+i1)/2; s[2] = ints[i1]; in[2] = i1;
  99. if (s[0] > s[1]) swap(s,in,0,1); if (s[1] > s[2]) swap(s,in,1,2); if (s[0] > s[1]) swap(s,in,0,1);
  100. // put the pivot at the beginning of the array
  101. int pivot = s[1]; int pivot_i = in[1];
  102. if (pivot_i == (i0+i1)/2) swap(ints,i0,(i0+i1)/2);
  103. else if (pivot_i == i1) swap(ints,i0,i1);
  104. // partition the array
  105. int i = i0+1, j = i1;
  106. while ((j-i) > 1) {
  107. while (i != j && ints[i] <= pivot) i++;
  108. while (i != j && ints[j] > pivot) j--;
  109. if (i != j) swap(ints,i,j);
  110. // for (int k=0;k<ints.length;k++) { if (k == i || k == j) System.out.print("["); System.out.print(ints[k]); if (k == i || k == j) System.out.print("]"); System.out.print(" "); } System.out.println();
  111. }
  112. // put the pivot in the middle
  113. if (ints[i] > pivot) { swap(ints,i-1,i0); pivot_i = i-1; }
  114. else { swap(ints,i, i0); pivot_i = i; }
  115. // partition the next set that contains the median
  116. if (pivot_i == ints.length/2) { return ints[ints.length/2]; }
  117. else if ((ints.length/2) < pivot_i) { /* i0 = i0; */ i1 = pivot_i-1; }
  118. else { i0 = pivot_i+1; /* i1 = i1; */ }
  119. // for (int k=0;k<ints.length;k++) { if (k == i0) System.out.print("<"); System.out.print(ints[k]); if (k == i1) System.out.print(">"); System.out.print(" "); } System.out.println();
  120. }
  121. }
  122. }
  123. protected void swap(int ints[], int i, int j) { int tmp = ints[i]; ints[i] = ints[j]; ints[j] = tmp; }
  124. protected void swap(int ints[], int ins[], int i, int j) { swap(ints,i,j); swap(ins,i,j); }
  125. /**
  126. * Return the minimum value from the list/array.
  127. *
  128. *@return min value
  129. */
  130. public double min() { return min_value; }
  131. /**
  132. * Return the maximum value from the list/array.
  133. *
  134. *@return max value
  135. */
  136. public double max() { return max_value; }
  137. /**
  138. * Return the median value from the list/array.
  139. *
  140. *@return median value
  141. */
  142. public double median() {
  143. if (Double.isNaN(median_value)) { median_value = qSortMedian(my_ints); }
  144. return median_value;
  145. }
  146. /**
  147. * Return the average value from the list/array.
  148. *
  149. *@return average value
  150. */
  151. public double average() { return sum/samples; }
  152. /**
  153. * Return the sum value of the list/array.
  154. */
  155. public double sum() { return sum; }
  156. /**
  157. * Return the standard deviation value from the list/array.
  158. *
  159. *@return standard deviation
  160. */
  161. public double stdev() {
  162. if (Double.isNaN(stdev_value)) {
  163. double avg = sum/samples;
  164. for (int i=0;i<my_ints.length;i++) {
  165. stdev_value += (my_ints[i] - avg) * (my_ints[i] - avg);
  166. }
  167. stdev_value = Math.sqrt(stdev_value/samples);
  168. }
  169. return stdev_value;
  170. }
  171. /**
  172. * Enumeration of stats
  173. */
  174. public enum STAT { MIN, MAX, SUM, MEDIAN, AVERAGE, STDEV };
  175. /**
  176. * Get a specific stat.
  177. *
  178. *@return stat
  179. */
  180. public double getStat(STAT stat) {
  181. switch (stat) {
  182. case MIN: return min();
  183. case MAX: return max();
  184. case SUM: return sum();
  185. case MEDIAN: return median();
  186. case AVERAGE: return average();
  187. case STDEV: return stdev();
  188. default: return sum();
  189. }
  190. }
  191. /**
  192. * Test for class
  193. */
  194. public static void main(String args[]) {
  195. for (int exp=1;exp<7;exp++) {
  196. int samples = (int) Math.pow(10,exp); System.out.println("**\n** Samples = " + samples + "\n**");
  197. for (int tests=0;tests<50;tests++) {
  198. int ints[] = new int[samples];
  199. for (int i=0;i<ints.length;i++) ints[i] = (int) (Math.random() * Integer.MAX_VALUE);
  200. long t0 = System.currentTimeMillis(); QuickStats qs = new QuickStats(ints); int median = (int) qs.median(); long t1 = System.currentTimeMillis();
  201. long t2 = System.currentTimeMillis(); Arrays.sort(ints); int median_r = ints[ints.length/2]; long t3 = System.currentTimeMillis();
  202. System.out.println("" + (median == median_r) + " med [" + median + "] t=" + (t1-t0) + " ...... acc [" + median_r + "] t=" + (t3-t2));
  203. }
  204. }
  205. }
  206. }