AverageTest.php 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522
  1. <?php
  2. namespace MathPHP\Tests\Statistics;
  3. use MathPHP\Statistics\Average;
  4. use MathPHP\Exception;
  5. class AverageTest extends \PHPUnit\Framework\TestCase
  6. {
  7. /**
  8. * @test mean
  9. * @dataProvider dataProviderForMean
  10. * @param array $numbers
  11. * @param float $expectedMean
  12. * @throws \Exception
  13. */
  14. public function testMean(array $numbers, float $expectedMean)
  15. {
  16. // When
  17. $mean = Average::mean($numbers);
  18. // Then
  19. $this->assertEqualsWithDelta($expectedMean, $mean, 0.01);
  20. }
  21. /**
  22. * @return array [numbers, mean]
  23. */
  24. public function dataProviderForMean(): array
  25. {
  26. return [
  27. [ [ 1, 1, 1 ], 1 ],
  28. [ [ 1, 2, 3 ], 2 ],
  29. [ [ 2, 3, 4 ], 3 ],
  30. [ [ 5, 5, 6 ], 5.33 ],
  31. [ [ 13, 18, 13, 14, 13, 16, 14, 21, 13 ], 15 ],
  32. [ [ 1, 2, 4, 7 ], 3.5 ],
  33. [ [ 8, 9, 10, 10, 10, 11, 11, 11, 12, 13 ], 10.5 ],
  34. [ [ 6, 7, 8, 10, 12, 14, 14, 15, 16, 20 ], 12.2 ],
  35. [ [ 9, 10, 11, 13, 15, 17, 17, 18, 19, 23 ], 15.2 ],
  36. [ [ 12, 14, 16, 20, 24, 28, 28, 30, 32, 40 ], 24.4 ],
  37. [ [1.1, 1.2, 1.3, 1.3, 1.4, 1.5 ], 1.3 ],
  38. ];
  39. }
  40. /**
  41. * @test mean when the input array is empty
  42. * @throws \Exception
  43. */
  44. public function testMeanExceptionWhenEmptyArray()
  45. {
  46. // Given
  47. $numbers = [];
  48. // Then
  49. $this->expectException(Exception\BadDataException::class);
  50. // When
  51. Average::mean($numbers);
  52. }
  53. /**
  54. * @test weightedMean
  55. * @dataProvider dataProviderForWeightedMean
  56. * @param array $numbers
  57. * @param array $weights
  58. * @param float $expectedMean
  59. * @throws \Exception
  60. */
  61. public function testWeightedMean(array $numbers, array $weights, float $expectedMean)
  62. {
  63. // When
  64. $mean = Average::weightedMean($numbers, $weights);
  65. // Then
  66. $this->assertEqualsWithDelta($expectedMean, $mean, 0.0001);
  67. }
  68. /**
  69. * @return array [numbers, weights, mean]
  70. */
  71. public function dataProviderForWeightedMean(): array
  72. {
  73. return [
  74. // Weights add up to 1
  75. [ [1, 3, 5, 7, 10], [1 / 5, 1 / 5, 1 / 5, 1 / 5, 1 / 5], 5.2],
  76. [ [1, 2, 3, 4], [1 / 4, 1 / 4, 1 / 4, 1 / 4], 2.5],
  77. [ [1, 2,3 , 4], [0.1, 0.1, 0.7, 0.1], 2.8],
  78. [ [8, 6, 7], [0.5, 0.3, 0.2], 7.2],
  79. [ [9, 4, 6], [0.5, 0.3, 0.2], 6.9],
  80. // Weights do not add at up 1
  81. [ [26, 3, 3, 20, 21, 14, 4, 16, 13, 14], [10, 29, 26, 18, 9, 20, 9, 14, 27, 9], 11.6433 ],
  82. [ [ 1, 2, 3 ], [ 1, 1, 1 ], 2 ],
  83. [ [ 2, 0.8, 2.9, 2.4, 2.8, 1.3, 2.7, 0.7, 0, 1.9 ], [2.1, 1.9, 0.5, 2.7, 1.9, 0.1, 1.5, 1.7, 2, 0.5], 1.69732 ],
  84. [ [70, 80, 90], [2, 3, 1], 78.3333],
  85. [ [1, 2, 5, 7], [2, 14, 8, 32], 5.25],
  86. ];
  87. }
  88. /**
  89. * @test weighted mean when the input array is empty
  90. * @throws \Exception
  91. */
  92. public function testWeightedMeanExceptionWhenEmptyArray()
  93. {
  94. // Given
  95. $numbers = [];
  96. $weights = [];
  97. // Then
  98. $this->expectException(Exception\BadDataException::class);
  99. // When
  100. Average::weightedMean($numbers, $weights);
  101. }
  102. /**
  103. * @test mean when the input array is empty
  104. * @dataProvider dataProviderForMean
  105. * @param array $numbers
  106. * @param float $expectedMean
  107. * @throws \Exception
  108. */
  109. public function testWeightedMeanIsJustMeanWhenEmptyWeights(array $numbers, float $expectedMean)
  110. {
  111. // When
  112. $mean = Average::weightedMean($numbers, []);
  113. // Then
  114. $this->assertEqualsWithDelta($expectedMean, $mean, 0.01);
  115. }
  116. /**
  117. * @test weightedMean throws a BadDataException when the numbers and weights don't have the same number of elements
  118. * @throws Exception\BadDataException
  119. */
  120. public function testWeightedMeanBadDataExceptionWhenCountsDoNotMatch()
  121. {
  122. // Given
  123. $numbers = [1, 2, 3];
  124. $weights = [1, 1];
  125. // Then
  126. $this->expectException(Exception\BadDataException::class);
  127. // When
  128. Average::weightedMean($numbers, $weights);
  129. }
  130. /**
  131. * @test median
  132. * @dataProvider dataProviderForMedian
  133. * @param array $numbers
  134. * @param float $expectedMedian
  135. * @throws \Exception
  136. */
  137. public function testMedian(array $numbers, float $expectedMedian)
  138. {
  139. // When
  140. $median = Average::median($numbers);
  141. // Then
  142. $this->assertEqualsWithDelta($expectedMedian, $median, 0.01);
  143. }
  144. /**
  145. * @test median when the input array is empty
  146. * @throws \Exception
  147. */
  148. public function testMedianExceptionWhenEmptyArray()
  149. {
  150. // Given
  151. $numbers = [];
  152. // Then
  153. $this->expectException(Exception\BadDataException::class);
  154. // When
  155. Average::median($numbers);
  156. }
  157. /**
  158. * @return array [numbers, median]
  159. */
  160. public function dataProviderForMedian(): array
  161. {
  162. return [
  163. [ [0], 0],
  164. [ [1], 1],
  165. [ [9], 9],
  166. [ [1, 1, 1 ], 1],
  167. [ [1, 2, 3 ], 2],
  168. [ [2, 3, 4 ], 3],
  169. [ [5, 5, 6 ], 5],
  170. [ [1, 2, 3, 4, 5], 3 ],
  171. [ [1, 2, 3, 4, 5, 6], 3.5 ],
  172. [ [13, 18, 13, 14, 13, 16, 14, 21, 13], 14 ],
  173. [ [1, 2, 4, 7], 3 ],
  174. [ [8, 9, 10, 10, 10, 11, 11, 11, 12, 13], 10.5 ],
  175. [ [6, 7, 8, 10, 12, 14, 14, 15, 16, 20], 13 ],
  176. [ [9, 10, 11, 13, 15, 17, 17, 18, 19, 23], 16 ],
  177. [ [12, 14, 16, 20, 24, 28, 28, 30, 32, 40], 26 ],
  178. [ [1.1, 1.2, 1.3, 1.4, 1.5], 1.3 ],
  179. [ [1.1, 1.2, 1.3, 1.3, 1.4, 1.5], 1.3 ],
  180. [ [1.1, 1.2, 1.3, 1.4], 1.25 ],
  181. ];
  182. }
  183. /**
  184. * @test kthSmallest
  185. * @dataProvider dataProviderForKthSmallest
  186. * @param array $numbers
  187. * @param int $k
  188. * @param float $expectedSmallest
  189. */
  190. public function testKthSmallest(array $numbers, int $k, float $expectedSmallest)
  191. {
  192. // When
  193. $smallest = Average::kthSmallest($numbers, $k);
  194. // Then
  195. $this->assertEquals($expectedSmallest, $smallest);
  196. }
  197. /**
  198. * @return array [numbers, k, smalest]
  199. */
  200. public function dataProviderForKthSmallest(): array
  201. {
  202. return [
  203. [ [ 1, 1, 1 ], 2, 1 ],
  204. [ [ 1, 2, 3 ], 1, 2 ],
  205. [ [ 2, 3, 4 ], 1, 3 ],
  206. [ [ 5, 5, 6 ], 0, 5 ],
  207. [ [ 1, 2, 3, 4, 5 ], 3, 4 ],
  208. [ [ 1, 2, 3, 4, 5, 6 ], 2, 3 ],
  209. [ [ 13, 18, 13, 14, 13, 16, 14, 21, 13 ], 7, 18 ],
  210. [ [ 1, 2, 4, 7 ], 2, 4 ],
  211. [ [ 8, 9, 10, 10, 10, 11, 11, 11, 12, 13 ], 5, 11 ],
  212. [ [ 6, 7, 8, 10, 12, 14, 14, 15, 16, 20 ], 7, 15 ],
  213. [ [ 9, 10, 11, 13, 15, 17, 17, 18, 19, 23 ], 9, 23 ],
  214. [ [ 12, 14, 16, 20, 24, 28, 28, 30, 32, 40 ], 1, 14 ],
  215. [ [1.1, 1.2, 1.3, 1.4, 1.5], 0, 1.1 ],
  216. [ [1.1, 1.2, 1.3, 1.4, 1.5], 1, 1.2 ],
  217. [ [1.1, 1.2, 1.3, 1.4, 1.5], 2, 1.3 ],
  218. [ [1.1, 1.2, 1.3, 1.4, 1.5], 3, 1.4 ],
  219. [ [1.1, 1.2, 1.3, 1.4, 1.5], 4, 1.5 ],
  220. ];
  221. }
  222. /**
  223. * @test kthSmallest when the input array is empty
  224. * @throws \Exception
  225. */
  226. public function testKthSmallestExceptionWhenEmptyArray()
  227. {
  228. // Given
  229. $numbers = [];
  230. $k = 1;
  231. // Then
  232. $this->expectException(Exception\BadDataException::class);
  233. // When
  234. Average::kthSmallest($numbers, $k);
  235. }
  236. /**
  237. * @test kthSmallest when k is larger than n
  238. * @throws \Exception
  239. */
  240. public function testKthSmallestExceptionWhenKIsLargerThanN()
  241. {
  242. // Given
  243. $numbers = [1, 2, 3];
  244. $k = 4;
  245. // Then
  246. $this->expectException(Exception\OutOfBoundsException::class);
  247. // When
  248. Average::kthSmallest($numbers, $k);
  249. }
  250. /**
  251. * @test mode
  252. * @dataProvider dataProviderForMode
  253. * @param array $numbers
  254. * @param array $modes
  255. * @throws \Exception
  256. */
  257. public function testMode(array $numbers, array $modes)
  258. {
  259. // When
  260. $computed_modes = Average::mode($numbers);
  261. sort($modes);
  262. sort($computed_modes);
  263. // Then
  264. $this->assertEquals($modes, $computed_modes);
  265. }
  266. /**
  267. * @array [numbers, modes]
  268. */
  269. public function dataProviderForMode(): array
  270. {
  271. return [
  272. [ [ 1, 1, 1 ], [1] ],
  273. [ [ 1, 1, 2 ], [1] ],
  274. [ [ 1, 2, 1 ], [1] ],
  275. [ [ 2, 1, 1 ], [1] ],
  276. [ [ 1, 2, 2 ], [2] ],
  277. [ [ 1, 1, 1, 1 ], [1] ],
  278. [ [ 1, 1, 1, 2 ], [1] ],
  279. [ [ 1, 1, 2, 1 ], [1] ],
  280. [ [ 1, 2, 1, 1 ], [1] ],
  281. [ [ 2, 1, 1, 1 ], [1] ],
  282. [ [ 1, 1, 2, 2 ], [ 1, 2 ] ],
  283. [ [ 1, 2, 2, 1 ], [ 1, 2 ] ],
  284. [ [ 2, 2, 1, 1 ], [ 1, 2 ] ],
  285. [ [ 2, 1, 2, 1 ], [ 1, 2 ] ],
  286. [ [ 2, 1, 1, 2 ], [ 1, 2 ] ],
  287. [ [ 1, 1, 2, 2, 3, 3 ], [ 1, 2, 3 ] ],
  288. [ [ 1, 2, 1, 2, 3, 3 ], [ 1, 2, 3 ] ],
  289. [ [ 1, 2, 3, 1, 2, 3 ], [ 1, 2, 3 ] ],
  290. [ [ 3, 1, 2, 3, 2, 1 ], [ 1, 2, 3 ] ],
  291. [ [ 3, 3, 2, 2, 1, 1 ], [ 1, 2, 3 ] ],
  292. [ [ 1, 1, 1, 2, 2, 3 ], [1] ],
  293. [ [ 1, 2, 2, 2, 2, 3 ], [2] ],
  294. [ [ 1, 2, 2, 3, 3, 4 ], [ 2, 3 ] ],
  295. [ [ 13, 18, 13, 14, 13, 16, 14, 21, 13 ], [13] ],
  296. [ [ 1, 2, 4, 7 ], [ 1, 2, 4, 7 ] ],
  297. [ [ 8, 9, 10, 10, 10, 11, 11, 11, 12, 13 ], [ 10, 11 ] ],
  298. [ [ 6, 7, 8, 10, 12, 14, 14, 15, 16, 20 ], [14] ],
  299. [ [ 9, 10, 11, 13, 15, 17, 17, 18, 19, 23 ], [17] ],
  300. [ [ 12, 14, 16, 20, 24, 28, 28, 30, 32, 40 ], [28] ],
  301. [ [ 1, 1.5, 2, 2 ], [2 ]],
  302. [ [ 1, 1.1, 1.2, 1.3, 1.3, 1.4, 1.4, 1.5, 1.6, 1.7, 2, 2.5 ], [1.3, 1.4] ],
  303. [ [ 1.2345678, 1.2345678, 1.23456, 1.23456789 ], [1.2345678] ],
  304. [ [ 1.2345678, 1.2345678, 1.23456, 1.23456789, 1.2232323, 1.4323432, 1.234432 ], [1.2345678] ],
  305. [ [ 231.424, 231.424, 333.2342, 34.23423, 354345345.23 ], [231.424] ],
  306. [ [ 1, 2, 2, 2, 3, 4.4, 4.4, 4.4, 5.6, 10], [2, 4.4] ],
  307. [ [ 1, 2.2, 2.20, 2.200, 3 ], [2.2] ],
  308. [ [ 1, 2.34354, 2.34354000, 4, 4, 5, 6 ], [2.34354, 4] ],
  309. [ [ 1, 2.458474748, 2.4584747480, 2.458474748000, 4, 4, 4, 5, 6 ], [2.45847474800, 4] ],
  310. ];
  311. }
  312. /**
  313. * @test mode when the input array is empty
  314. * @throws \Exception
  315. */
  316. public function testModeEmptyArrayWhenEmptyArray()
  317. {
  318. // Given
  319. $numbers = [];
  320. // Then
  321. $this->expectException(Exception\BadDataException::class);
  322. // When
  323. Average::mode($numbers);
  324. }
  325. /**
  326. * @test geometricMean
  327. * @dataProvider dataProviderForGeometricMean
  328. * @param array $numbers
  329. * @param float $expectedMean
  330. * @throws \Exception
  331. */
  332. public function testGeometricMean(array $numbers, float $expectedMean)
  333. {
  334. // When
  335. $mean = Average::geometricMean($numbers);
  336. // Then
  337. $this->assertEqualsWithDelta($expectedMean, $mean, 0.01);
  338. }
  339. /**
  340. * @return array [numbers, mean]
  341. */
  342. public function dataProviderForGeometricMean(): array
  343. {
  344. return [
  345. [ [ 1, 1, 1 ], 1 ],
  346. [ [ 1, 2, 3 ], 1.81712 ],
  347. [ [ 2, 3, 4 ], 2.8845 ],
  348. [ [ 5, 5, 6 ], 5.31329 ],
  349. [ [ 13, 18, 13, 14, 13, 16, 14, 21, 13 ], 14.78973 ],
  350. [ [ 1, 2, 4, 7 ], 2.73556 ],
  351. [ [ 8, 9, 10, 10, 10, 11, 11, 11, 12, 13 ], 10.41031 ],
  352. [ [ 6, 7, 8, 10, 12, 14, 14, 15, 16, 20 ], 11.4262 ],
  353. [ [ 9, 10, 11, 13, 15, 17, 17, 18, 19, 23 ], 14.59594 ],
  354. [ [ 12, 14, 16, 20, 24, 28, 28, 30, 32, 40 ], 22.8524 ],
  355. [ [ 1, 3, 5, 7, 10 ], 4.02011 ],
  356. ];
  357. }
  358. /**
  359. * @test geometricMean when the input array is empty
  360. */
  361. public function testGeometricMeanExceptionWhenEmptyArray()
  362. {
  363. // Given
  364. $numbers = [];
  365. // Then
  366. $this->expectException(Exception\BadDataException::class);
  367. // When
  368. Average::geometricMean($numbers);
  369. }
  370. /**
  371. * @test harmonicMean
  372. * @dataProvider dataProviderForHarmonicMean
  373. * @param array $numbers
  374. * @param float $expectedMean
  375. * @throws \Exception
  376. */
  377. public function testHarmonicMean(array $numbers, float $expectedMean)
  378. {
  379. // When
  380. $mean = Average::harmonicMean($numbers);
  381. // Then
  382. $this->assertEqualsWithDelta($expectedMean, $mean, 0.01);
  383. }
  384. /**
  385. * @return array [numbers, float]
  386. */
  387. public function dataProviderForHarmonicMean(): array
  388. {
  389. return [
  390. [ [ 1, 2, 4, ], 1.71429 ],
  391. [ [ 1, 1, 1 ], 1 ],
  392. [ [ 1, 2, 3 ], 1.63636 ],
  393. [ [ 2, 3, 4 ], 2.76923 ],
  394. [ [ 5, 5, 6 ], 5.29412 ],
  395. [ [ 13, 18, 13, 14, 13, 16, 14, 21, 13 ], 14.60508 ],
  396. [ [ 1, 2, 4, 7 ], 2.11321 ],
  397. [ [ 8, 9, 10, 10, 10, 11, 11, 11, 12, 13 ], 10.31891 ],
  398. [ [ 6, 7, 8, 10, 12, 14, 14, 15, 16, 20 ], 10.63965 ],
  399. [ [ 9, 10, 11, 13, 15, 17, 17, 18, 19, 23 ], 13.98753 ],
  400. [ [ 12, 14, 16, 20, 24, 28, 28, 30, 32, 40 ], 21.27929 ],
  401. [ [ 1, 3, 5, 7, 10 ], 2.81501 ],
  402. ];
  403. }
  404. /**
  405. * @test harmonicMean when the input array is empty
  406. * @throws \Exception
  407. */
  408. public function testHarmonicMeanNullWhenEmptyArray()
  409. {
  410. // Given
  411. $numbers = [];
  412. // Then
  413. $this->expectException(Exception\BadDataException::class);
  414. // When
  415. Average::harmonicMean($numbers);
  416. }
  417. /**
  418. * @test harmonicMean with negative values
  419. * @throws \Exception
  420. */
  421. public function testHarmonicMeanExceptionNegativeValues()
  422. {
  423. // Given
  424. $numbers = [ 1, 2, 3, -4, 5, -6, 7 ];
  425. // Then
  426. $this->expectException(Exception\BadDataException::class);
  427. // When
  428. Average::harmonicMean($numbers);
  429. }
  430. /**
  431. * @test rootMeanSquare
  432. * @dataProvider dataProviderForRootMeanSquare
  433. * @param array $numbers
  434. * @param float $expectedRms
  435. */
  436. public function testRootMeanSquare(array $numbers, float $expectedRms)
  437. {
  438. // When
  439. $rms = Average::rootMeanSquare($numbers);
  440. // Then
  441. $this->assertEqualsWithDelta($expectedRms, $rms, 0.01);
  442. }
  443. /**
  444. * @test quadradicMean
  445. * @dataProvider dataProviderForRootMeanSquare
  446. * @param array $numbers
  447. * @param float $expectedRms
  448. */
  449. public function testQuadradicMean(array $numbers, float $expectedRms)
  450. {
  451. // When
  452. $rms = Average::quadraticMean($numbers);
  453. // Then
  454. $this->assertEqualsWithDelta($expectedRms, $rms, 0.01);
  455. }
  456. /**
  457. * @return array [numbers, rms]
  458. */
  459. public function dataProviderForRootMeanSquare(): array
  460. {
  461. return [
  462. [ [0, 0, 0], 0 ],
  463. [ [1, 2, 3, 4, 5, 6], 3.89444 ],
  464. [ [0.001, 0.039, 0.133, 0.228, 0.374], 0.20546 ],
  465. [ [3, 5, 6, 3, 3535, 234, 0, 643, 2], 1200.209 ],
  466. ];
  467. }
  468. /**
  469. * @test rootMeanSquare with empty list of numbers
  470. * @throws \Exception
  471. */
  472. public function testRootMeanSquareExceptionWhenEmptyList()
  473. {
  474. // Given
  475. $numbers = [];
  476. // Then
  477. $this->expectException(Exception\BadDataException::class);
  478. // When
  479. Average::rootMeanSquare($numbers);
  480. }
  481. /**
  482. * @test quadraticMean with empty list of numbers
  483. * @throws \Exception
  484. */
  485. public function testQuadraticMeanExceptionWhenEmptyList()
  486. {
  487. // Given
  488. $numbers = [];
  489. // Then
  490. $this->expectException(Exception\BadDataException::class);
  491. // When
  492. Average::quadraticMean($numbers);
  493. }
  494. /**
  495. * @test trimean
  496. * @dataProvider dataProviderForTrimean
  497. * @param array $numbers
  498. * @param float $expectedTrimean
  499. * @throws \Exception
  500. */
  501. public function testTrimean(array $numbers, float $expectedTrimean)
  502. {
  503. // When
  504. $trimean = Average::trimean($numbers);
  505. // Then
  506. $this->assertEqualsWithDelta($expectedTrimean, $trimean, 0.1);
  507. }
  508. /**
  509. * @return array [numbers, trimean]
  510. */
  511. public function dataProviderForTrimean(): array
  512. {
  513. return [
  514. [ [ 155, 158, 161, 162, 166, 170, 171, 174, 179 ], 166 ],
  515. [ [ 162, 162, 163, 165, 166, 175, 181, 186, 192 ], 169.5 ],
  516. [ [ 1, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 11, 12, 13 ], 7.25 ],
  517. [ [ 1, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 11, 12, 1000 ], 7.25 ],
  518. ];
  519. }
  520. /**
  521. * @test truncatedMean
  522. * @dataProvider dataProviderForTruncatedMean
  523. * @param array $numbers
  524. * @param int $trim_percent
  525. * @param float $expectedMean
  526. * @throws \Exception
  527. */
  528. public function testTruncatedMean(array $numbers, int $trim_percent, float $expectedMean)
  529. {
  530. // When
  531. $mean = Average::truncatedMean($numbers, $trim_percent);
  532. // Then
  533. $this->assertEqualsWithDelta($expectedMean, $mean, 0.00001);
  534. }
  535. /**
  536. * Test data generated with R: mean(nums, trim=0.05)
  537. * @return array [numbers, trim_percent, mean]
  538. */
  539. public function dataProviderForTruncatedMean(): array
  540. {
  541. return [
  542. [[92, 19, 101, 58, 1053, 91, 26, 78, 10, 13, -40, 101, 86, 85, 15, 89, 89, 28, -5, 41], 0, 101.5],
  543. [[92, 19, 101, 58, 1053, 91, 26, 78, 10, 13, -40, 101, 86, 85, 15, 89, 89, 28, -5, 41], 5, 56.5],
  544. [[92, 19, 101, 58, 1053, 91, 26, 78, 10, 13, -40, 101, 86, 85, 15, 89, 89, 28, -5, 41], 15, 57.85714],
  545. [[92, 19, 101, 58, 1053, 91, 26, 78, 10, 13, -40, 101, 86, 85, 15, 89, 89, 28, -5, 41], 40, 65.5],
  546. [[92, 19, 101, 58, 1053, 91, 26, 78, 10, 13, -40, 101, 86, 85, 15, 89, 89, 28, -5, 41], 50, 68],
  547. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 0, 12.30769],
  548. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 5, 12.30769],
  549. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 10, 9.545455],
  550. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 20, 8.777778],
  551. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 25, 7.714286],
  552. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 30, 7.714286],
  553. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 35, 7.6],
  554. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 40, 7.333333],
  555. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 45, 7.333333],
  556. [[4,3,6,8,4,2,4,8,12,53,23,12,21], 50, 8],
  557. [[8, 3, 7, 1, 3, 9], 0, 5.16666667],
  558. [[8, 3, 7, 1, 3, 9], 20, 5.25],
  559. [[8, 3, 7, 1, 3, 9], 50, 5],
  560. [[6,4,2,4,3,7,6,33,77,22,3,5,6,5,0,2,3,4,6], 25, 4.727273],
  561. [[6,4,2,4,3,7,6,33,77,22,3,5,6,5,0,2,3,4,6], 50, 5],
  562. [[2, 3, 4, 5, 1, 9, 6, 7, 10, 8], 1, 5.5],
  563. [[2, 3, 4, 5, 1, 9, 6, 7, 10, 8], 10, 5.5],
  564. [[2, 3, 4, 5, 1, 9, 6, 7, 10, 8], 40, 5.5],
  565. [[2, 3, 4, 5, 1, 9, 6, 7, 10, 8], 50, 5.5],
  566. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 1, 5.142857],
  567. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 1, 5.142857],
  568. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 10, 4.647059],
  569. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 20, 4.461538],
  570. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 25, 4.454545],
  571. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 40, 4.4],
  572. [[3, 5, 6, 7, 6, 5, 6, 4, 2, 1, 0, 9, 8, 2, 4, 16, 4, 3, 3, 2, 12], 50, 4],
  573. [[1, 2, 3], 50, 2],
  574. [[1, 2, 3, 4], 50, 2.5],
  575. [[1, 2, 3, 4, 5], 50, 3],
  576. [[1, 2, 3, 4, 5, 6], 50, 3.5],
  577. ];
  578. }
  579. /**
  580. * @test truncatedMean of an empty list
  581. * @throws \Exception
  582. */
  583. public function testTruncatedMeanExceptionEmptyList()
  584. {
  585. // Given
  586. $numbers = [];
  587. $trim_percent = 5;
  588. // Then
  589. $this->expectException(Exception\BadDataException::class);
  590. // When
  591. Average::truncatedMean($numbers, $trim_percent);
  592. }
  593. /**
  594. * @test truncatedMean trim percent is less than zero
  595. * @throws \Exception
  596. */
  597. public function testTruncatedMeanExceptionLessThanZeroTrimPercent()
  598. {
  599. // Given
  600. $numbers = [1, 2, 3];
  601. $trim_percent = -1;
  602. // Then
  603. $this->expectException(Exception\OutOfBoundsException::class);
  604. // When
  605. Average::truncatedMean($numbers, $trim_percent);
  606. }
  607. /**
  608. * @test truncatedMean trim percent greater than 50
  609. * @dataProvider dataProviderForTruncatedMeanGreaterThan50TrimPercent
  610. * @param int $trim_percent
  611. */
  612. public function testTruncatedMeanExceptionGreaterThan50TrimPercent(int $trim_percent)
  613. {
  614. // Given
  615. $numbers = [1, 2, 3, 6, 5, 4, 7];
  616. // Then
  617. $this->expectException(Exception\OutOfBoundsException::class);
  618. // When
  619. Average::truncatedMean([1, 2, 3], $trim_percent);
  620. }
  621. public function dataProviderForTruncatedMeanGreaterThan50TrimPercent(): array
  622. {
  623. return [
  624. [51],
  625. [75],
  626. [99],
  627. [100],
  628. [101],
  629. ];
  630. }
  631. /**
  632. * @test interquartileMean
  633. * @dataProvider dataProviderForInterquartileMean
  634. * @param array $numbers
  635. * @param float $expectedIqm
  636. * @throws \Exception
  637. */
  638. public function testInterquartileMean(array $numbers, float $expectedIqm)
  639. {
  640. // When
  641. $iqm = Average::interquartileMean($numbers);
  642. // Then
  643. $this->assertEqualsWithDelta($expectedIqm, $iqm, 0.01);
  644. }
  645. /**
  646. * @test iqm
  647. * @dataProvider dataProviderForInterquartileMean
  648. * @param array $numbers
  649. * @param float $expectedIqm
  650. * @throws \Exception
  651. */
  652. public function testIqm(array $numbers, float $expectedIqm)
  653. {
  654. // When
  655. $iqm = Average::iqm($numbers);
  656. // Then
  657. $this->assertEqualsWithDelta($expectedIqm, $iqm, 0.01);
  658. }
  659. /**
  660. * @return array [numbers, iqm]
  661. */
  662. public function dataProviderForInterquartileMean(): array
  663. {
  664. return [
  665. [ [5, 8, 4, 38, 8, 6, 9, 7, 7, 3, 1, 6], 6.5 ],
  666. [ [1, 3, 5, 7, 9, 11, 13, 15, 17], 9 ]
  667. ];
  668. }
  669. /**
  670. * @test cubicMean
  671. * @dataProvider dataProviderForCubicMean
  672. * @throws \Exception
  673. */
  674. public function testCubicMean(array $numbers, float $expectedMean)
  675. {
  676. // When
  677. $mean = Average::cubicMean($numbers);
  678. // Then
  679. $this->assertEqualsWithDelta($expectedMean, $mean, 0.001);
  680. }
  681. /**
  682. * @return array
  683. */
  684. public function dataProviderForCubicMean(): array
  685. {
  686. return [
  687. [[1, 2, 3], 2.289428485106664],
  688. [[0, 5, 9, 4], 6.122482652876022],
  689. ];
  690. }
  691. /**
  692. * @test cubic mean with empty list of numbers
  693. * @throws \Exception
  694. */
  695. public function testCubicMeanExceptionWhenEmptyList()
  696. {
  697. // Given
  698. $numbers = [];
  699. // Then
  700. $this->expectException(Exception\BadDataException::class);
  701. // When
  702. Average::cubicMean($numbers);
  703. }
  704. /**
  705. * @test lehmerMean
  706. * @dataProvider dataProviderForLehmerMean
  707. * @param array $numbers
  708. * @param float $p
  709. * @param float $expectedMean
  710. */
  711. public function testLehmerMean(array $numbers, float $p, float $expectedMean)
  712. {
  713. // When
  714. $mean = Average::lehmerMean($numbers, $p);
  715. // Then
  716. $this->assertEqualsWithDelta($expectedMean, $mean, 0.01);
  717. }
  718. /**
  719. * @return array [numbers, p, mean]
  720. */
  721. public function dataProviderForLehmerMean(): array
  722. {
  723. return [
  724. [ [ 3, 6, 2, 9, 1, 7, 2 ], -2, 1.290 ],
  725. [ [ 3, 6, 2, 9, 1, 7, 2 ], -1, 1.647 ],
  726. [ [ 3, 6, 2, 9, 1, 7, 2 ], -0.5, 1.997 ],
  727. [ [ 3, 6, 2, 9, 1, 7, 2 ], 0.5, 3.322 ],
  728. [ [ 3, 6, 2, 9, 1, 7, 2 ], 1, 4.286 ],
  729. [ [ 3, 6, 2, 9, 1, 7, 2 ], 2, 6.133 ],
  730. [ [ 3, 6, 2, 9, 1, 7, 2 ], 3, 7.239 ],
  731. ];
  732. }
  733. /**
  734. * @test lehmerMean with empty list of numbers
  735. * @throws \Exception
  736. */
  737. public function testLehmerMeanExceptionWhenEmptyList()
  738. {
  739. // Given
  740. $numbers = [];
  741. $p = 1;
  742. // Then
  743. $this->expectException(Exception\BadDataException::class);
  744. // When
  745. Average::lehmerMean($numbers, $p);
  746. }
  747. /**
  748. * @test lehmerMean p is negative infinity
  749. */
  750. public function testLehmerMeanPEqualsNegativeInfinityIsMin()
  751. {
  752. // Given
  753. $numbers = [ 3, 6, 2, 9, 1, 7, 2];
  754. $p = -\INF;
  755. // When
  756. $mean = Average::lehmerMean($numbers, $p);
  757. // Then
  758. $this->assertEquals(\min($numbers), $mean);
  759. }
  760. /**
  761. * @test lehmerMean p is infinity
  762. */
  763. public function testLehmerMeanPEqualsInfinityIsMax()
  764. {
  765. // Given
  766. $numbers = [ 3, 6, 2, 9, 1, 7, 2];
  767. $p = \INF;
  768. // When
  769. $mean = Average::lehmerMean($numbers, $p);
  770. // Then
  771. $this->assertEquals(\max($numbers), $mean);
  772. }
  773. /**
  774. * @test lehmerMean with a p of zero is the harmonic mean
  775. * @throws \Exception
  776. */
  777. public function testLehmerMeanPEqualsZeroIsHarmonicMean()
  778. {
  779. // Given
  780. $numbers = [ 3, 6, 2, 9, 1, 7, 2];
  781. $p = 0;
  782. // When
  783. $mean = Average::lehmerMean($numbers, $p);
  784. // Then
  785. $this->assertEquals(Average::harmonicMean($numbers), $mean);
  786. }
  787. /**
  788. * @test lehmerMean with a p of one half is the geometric mean
  789. * @throws \Exception
  790. */
  791. public function testLehmerMeanPEqualsOneHalfIsGeometricMean()
  792. {
  793. // Given
  794. $numbers = [3, 6];
  795. $p = 1 / 2;
  796. // When
  797. $mean = Average::lehmerMean($numbers, $p);
  798. // Then
  799. $this->assertEqualsWithDelta(Average::geometricMean($numbers), $mean, 0.00001);
  800. }
  801. /**
  802. * @test lehmerMean with a p of one is the arithmetic mean
  803. * @throws \Exception
  804. */
  805. public function testLehmerMeanPEqualsOneIsArithmeticMean()
  806. {
  807. // Given
  808. $numbers = [ 3, 6, 2, 9, 1, 7, 2];
  809. $p = 1;
  810. // When
  811. $mean = Average::lehmerMean($numbers, $p);
  812. // Then
  813. $this->assertEquals(Average::mean($numbers), $mean);
  814. }
  815. /**
  816. * @test generalizedMean
  817. * @dataProvider dataProviderForGeneralizedMean
  818. * @param array $numbers
  819. * @param float $p
  820. * @param float $expectedMean
  821. * @throws \Exception
  822. */
  823. public function testGeneralizedMean(array $numbers, float $p, float $expectedMean)
  824. {
  825. // When
  826. $mean = Average::generalizedMean($numbers, $p);
  827. // Then
  828. $this->assertEqualsWithDelta($expectedMean, $mean, 0.001);
  829. }
  830. /**
  831. * @test generalizedMean with empty list of numbers
  832. * @throws \Exception
  833. */
  834. public function testGeneralizedMeanExceptionWhenEmptyList()
  835. {
  836. // Given
  837. $numbers = [];
  838. $p = 1;
  839. // Then
  840. $this->expectException(Exception\BadDataException::class);
  841. // When
  842. Average::generalizedMean($numbers, $p);
  843. }
  844. /**
  845. * @test powerMean
  846. * @dataProvider dataProviderForGeneralizedMean
  847. * @param array $numbers
  848. * @param float $p
  849. * @param float $expectedMean
  850. */
  851. public function testPowerMean(array $numbers, float $p, float $expectedMean)
  852. {
  853. // When
  854. $mean = Average::powerMean($numbers, $p);
  855. // Then
  856. $this->assertEqualsWithDelta($expectedMean, $mean, 0.001);
  857. }
  858. /**
  859. * @return array [numbers, float, mean]
  860. */
  861. public function dataProviderForGeneralizedMean(): array
  862. {
  863. return [
  864. [ [1, 2, 3, 4, 5], -2, 1.84829867963 ],
  865. [ [1, 2, 3, 4, 5], -1, 2.1897810219 ],
  866. [ [1, 2, 3, 4, 5], -0.5, 2.3937887509 ],
  867. [ [1, 2, 3, 4, 5], 0.5, 2.81053982332 ],
  868. [ [1, 2, 3, 4, 5], 1, 3 ],
  869. [ [1, 2, 3, 4, 5], 2, 3.31662479036 ],
  870. [ [1, 2, 3, 4, 5], 3, 3.55689330449 ],
  871. ];
  872. }
  873. /**
  874. * @test generalizedMean with a p of negative infinity
  875. * @throws \Exception
  876. */
  877. public function testGeneralizedMeanPEqualsNegativeInfinityIsMin()
  878. {
  879. // Given
  880. $numbers = [3, 6, 2, 9, 1, 7, 2];
  881. $p = -\INF;
  882. // When
  883. $mean = Average::generalizedMean($numbers, $p);
  884. // Then
  885. $this->assertEquals(\min($numbers), $mean);
  886. }
  887. /**
  888. * @test generalizedMean with a p of infinity
  889. * @throws \Exception
  890. */
  891. public function testGeneralizedMeanPEqualsInfinityIsMax()
  892. {
  893. // Given
  894. $numbers = [3, 6, 2, 9, 1, 7, 2];
  895. $p = \INF;
  896. // When
  897. $mean = Average::generalizedMean($numbers, $p);
  898. // Then
  899. $this->assertEquals(\max($numbers), $mean);
  900. }
  901. /**
  902. * @test generalizedMean with a p of negative one is the harmonic mean
  903. * @throws \Exception
  904. */
  905. public function testGeneralizedMeanPEqualsNegativeOneIsHarmonicMean()
  906. {
  907. // Given
  908. $numbers = [3, 6, 2, 9, 1, 7, 2];
  909. $p = -1;
  910. // When
  911. $mean = Average::generalizedMean($numbers, $p);
  912. // Then
  913. $this->assertEquals(Average::harmonicMean($numbers), $mean);
  914. }
  915. /**
  916. * @test generalizedMean with a p of zero is the geometric mean
  917. * @throws \Exception
  918. */
  919. public function testGeneralizedMeanPEqualsZeroIsGeometricMean()
  920. {
  921. $numbers = [ 3, 6, 2, 9, 1, 7, 2];
  922. $p = 0;
  923. $this->assertEquals(Average::geometricMean($numbers), Average::generalizedMean($numbers, $p));
  924. }
  925. /**
  926. * @test generalizedMean with a p of one is the arithmetic mean
  927. * @throws \Exception
  928. */
  929. public function testGeneralizedMeanPEqualsOneIsArithmeticMean()
  930. {
  931. // Given
  932. $numbers = [3, 6, 2, 9, 1, 7, 2];
  933. $p = 1;
  934. // When
  935. $mean = Average::generalizedMean($numbers, $p);
  936. // Then
  937. $this->assertEquals(Average::mean($numbers), $mean);
  938. }
  939. /**
  940. * @test generalizedMean with a p of two is the quadratic mean
  941. * @throws \Exception
  942. */
  943. public function testGeneralizedMeanPEqualsTwoIsQuadraticMean()
  944. {
  945. // Given
  946. $numbers = [3, 6, 2, 9, 1, 7, 2];
  947. $p = 2;
  948. // When
  949. $mean = Average::generalizedMean($numbers, $p);
  950. // Then
  951. $this->assertEquals(Average::quadraticMean($numbers), $mean);
  952. }
  953. /**
  954. * @test generalizedMean with a p of three is the cubic mean
  955. * @throws \Exception
  956. */
  957. public function testGeneralizedMeanPEqualsThreeIsCubicMean()
  958. {
  959. // Given
  960. $numbers = [3, 6, 2, 9, 1, 7, 2];
  961. $p = 3;
  962. // When
  963. $mean = Average::generalizedMean($numbers, $p);
  964. // Then
  965. $this->assertEquals(Average::cubicMean($numbers), $mean);
  966. }
  967. /**
  968. * @test contraharmonicMean
  969. */
  970. public function testContraharmonicMean()
  971. {
  972. // Given
  973. $numbers = [3, 6, 2, 9, 1, 7, 2];
  974. // When
  975. $mean = Average::contraharmonicMean($numbers);
  976. // Then
  977. $this->assertEqualsWithDelta(6.133, $mean, 0.01);
  978. }
  979. /**
  980. * @test simpleMovingAverage
  981. * @dataProvider dataProviderForSimpleMovingAverage
  982. * @param array $numbers
  983. * @param int $n
  984. * @param array $expectedSma
  985. */
  986. public function testSimpleMovingAverage(array $numbers, int $n, array $expectedSma)
  987. {
  988. // When
  989. $sma = Average::simpleMovingAverage($numbers, $n);
  990. // Then
  991. $this->assertEqualsWithDelta($expectedSma, $sma, 0.0001);
  992. }
  993. /**
  994. * @return array [numbers, int, SMA]
  995. */
  996. public function dataProviderForSimpleMovingAverage(): array
  997. {
  998. return [
  999. [
  1000. [1, 1, 2, 2, 3, 3], 2,
  1001. [1, 1.5, 2, 2.5, 3],
  1002. ],
  1003. [
  1004. [10, 11, 11, 15, 13, 14, 12, 10, 11], 4,
  1005. [11.75, 12.5, 13.25, 13.5, 12.25, 11.75],
  1006. ],
  1007. [
  1008. [11, 12, 13, 14, 15, 16, 17], 5,
  1009. [13, 14, 15],
  1010. ],
  1011. [
  1012. [4, 6, 5, 8, 9, 5, 4, 3, 7, 8], 5,
  1013. [6.4, 6.6, 6.2, 5.8, 5.6, 5.4],
  1014. ],
  1015. [
  1016. [43, 67, 57, 67, 4, 32, 34, 54, 93, 94, 38, 45], 6,
  1017. [45, 43.5, 41.3333, 47.3333, 51.8333, 57.5, 59.6667],
  1018. ],
  1019. [
  1020. [5, 6, 7, 8, 9], 3,
  1021. [6, 7, 8]
  1022. ],
  1023. ];
  1024. }
  1025. /**
  1026. * @test cumulativeMovingAverage
  1027. * @dataProvider dataProviderForCumulativeMovingAverage
  1028. * @param array $numbers
  1029. * @param array $expectredCma
  1030. */
  1031. public function testCumulativeMovingAverage(array $numbers, array $expectredCma)
  1032. {
  1033. // When
  1034. $cma = Average::cumulativeMovingAverage($numbers);
  1035. // Then
  1036. $this->assertEqualsWithDelta($expectredCma, $cma, 0.001);
  1037. }
  1038. /**
  1039. * @return array [numbers, CMA]
  1040. */
  1041. public function dataProviderForCumulativeMovingAverage(): array
  1042. {
  1043. return [
  1044. [
  1045. [1, 2, 3, 4, 5],
  1046. [1, 1.5, 2, 2.5, 3],
  1047. ],
  1048. [
  1049. [1, 1, 2, 2, 3, 3],
  1050. [1, 1, 1.333, 1.5, 1.8, 2],
  1051. ],
  1052. [
  1053. [1, 3, 8, 12, 10, 8, 7, 15],
  1054. [1, 2, 4, 6, 6.8, 7, 7, 8],
  1055. ],
  1056. ];
  1057. }
  1058. /**
  1059. * @test weightedMovingAverage
  1060. * @dataProvider dataProviderForWeightedMovingAverage
  1061. * @param array $numbers
  1062. * @param int $n
  1063. * @param array $weights
  1064. * @param array $expectedWma
  1065. * @throws \Exception
  1066. */
  1067. public function testWeightedMovingAverage(array $numbers, int $n, array $weights, array $expectedWma)
  1068. {
  1069. // When
  1070. $wma = Average::weightedMovingAverage($numbers, $n, $weights);
  1071. // Then
  1072. $this->assertEqualsWithDelta($expectedWma, $wma, 0.001);
  1073. }
  1074. /**
  1075. * @return array [numbers, n, weights, WMA]
  1076. */
  1077. public function dataProviderForWeightedMovingAverage(): array
  1078. {
  1079. return [
  1080. [
  1081. [10, 11, 15, 16, 14, 12, 10, 11],
  1082. 3,
  1083. [1, 2, 5],
  1084. [13.375, 15.125, 14.625, 13, 11, 10.875],
  1085. ],
  1086. [
  1087. [5, 4, 8],
  1088. 3,
  1089. [1, 2, 3],
  1090. [6.16666667]
  1091. ],
  1092. [
  1093. [5, 6, 7, 8, 9],
  1094. 5,
  1095. [1, 2, 3, 4, 5],
  1096. [7.6667],
  1097. ],
  1098. ];
  1099. }
  1100. /**
  1101. * @test weightedMovingAverage weights differ from n
  1102. * @throws \Exception
  1103. */
  1104. public function testWeightedMovingAverageExceptionWeightsDifferFromN()
  1105. {
  1106. // Given
  1107. $numbers = [1, 2, 3, 4, 5, 6];
  1108. $n = 3;
  1109. $weights = [1, 2];
  1110. // Then
  1111. $this->expectException(Exception\BadDataException::class);
  1112. // When
  1113. Average::weightedMovingAverage($numbers, $n, $weights);
  1114. }
  1115. /**
  1116. * @test exponentialMovingAverage
  1117. * @dataProvider dataProviderForExponentialMovingAverage
  1118. * @param array $numbers
  1119. * @param int $n
  1120. * @param array $expectedEma
  1121. */
  1122. public function testExponentialMovingAverage(array $numbers, int $n, array $expectedEma)
  1123. {
  1124. // When
  1125. $ema = Average::exponentialMovingAverage($numbers, $n);
  1126. // Then
  1127. $this->assertEqualsWithDelta($expectedEma, $ema, 0.01);
  1128. }
  1129. /**
  1130. * @return array [numbers, n, EMA]
  1131. */
  1132. public function dataProviderForExponentialMovingAverage(): array
  1133. {
  1134. return [
  1135. [
  1136. [1, 1, 2, 2, 3, 3], 2,
  1137. [1, 1, 1.667, 1.889, 2.63, 2.877],
  1138. ],
  1139. [
  1140. [5, 6, 7, 8, 7, 8, 9, 8, 7], 2,
  1141. [5, 5.667, 6.556, 7.519, 7.173, 7.724, 8.575, 8.192, 7.397],
  1142. ],
  1143. [
  1144. [5, 6, 7, 8, 7, 8, 9, 8, 7], 3,
  1145. [5, 5.5, 6.25, 7.125, 7.063, 7.531, 8.266, 8.133, 7.566],
  1146. ],
  1147. [
  1148. [22, 25, 27, 29, 34, 46, 43, 39, 37, 36, 36, 35, 34, 40, 43, 44, 49, 50, 52, 47, 35, 32, 29, 15, 17, 18, 19], 3,
  1149. [22, 23.5, 25.25, 27.125, 30.563, 38.281, 40.641, 39.82, 38.41, 37.205, 36.603, 35.801, 34.901, 37.45, 40.225, 42.113, 45.556, 47.778, 49.889, 48.445, 41.722, 36.861, 32.931, 23.965, 20.483, 19.241, 19.121]
  1150. ],
  1151. [
  1152. [22.81, 23.09, 22.91, 23.23, 22.83, 23.05, 23.02, 23.29, 23.41, 23.49, 24.60, 24.63, 24.51, 23.73, 23.31, 23.53, 23.06, 23.25, 23.12, 22.80, 22.84], 9,
  1153. [22.81, 22.87, 22.87, 22.95, 22.92, 22.95, 22.96, 23.03, 23.10, 23.18, 23.47, 23.70, 23.86, 23.83, 23.73, 23.69, 23.56, 23.50, 23.42, 23.30, 23.21]
  1154. ],
  1155. [
  1156. [10, 15, 17, 20, 22, 20, 25, 27, 30, 35, 37, 40], 3,
  1157. [10, 12.5, 14.75, 17.375, 19.688, 19.844, 22.422, 24.711, 27.355, 31.178, 34.089, 37.044]
  1158. ],
  1159. ];
  1160. }
  1161. /**
  1162. * @test arithmeticGeometricMean
  1163. * @dataProvider dataProviderForArithmeticGeometricMean
  1164. * @param float $x
  1165. * @param float $y
  1166. * @param float $expectedMean
  1167. */
  1168. public function testArithmeticGeometricMean(float $x, float $y, float $expectedMean)
  1169. {
  1170. // When
  1171. $mean = Average::arithmeticGeometricMean($x, $y);
  1172. // Then
  1173. $this->assertEqualsWithDelta($expectedMean, $mean, 0.00001);
  1174. }
  1175. /**
  1176. * @test agm
  1177. * @dataProvider dataProviderForArithmeticGeometricMean
  1178. * @param float $x
  1179. * @param float $y
  1180. * @param float $expectedMean
  1181. */
  1182. public function testAGM(float $x, float $y, float $expectedMean)
  1183. {
  1184. // When
  1185. $mean = Average::agm($x, $y);
  1186. // Then
  1187. $this->assertEqualsWithDelta($expectedMean, $mean, 0.00001);
  1188. }
  1189. /**
  1190. * @return array [x, y, mean]
  1191. */
  1192. public function dataProviderForArithmeticGeometricMean(): array
  1193. {
  1194. return [
  1195. [ 24, 6, 13.4581714817256154207668131569743992430538388544 ],
  1196. [ 2, 4, 2.913582062093814 ],
  1197. [ 1, 1, 1 ],
  1198. [ 43.6, 7765.332, 1856.949564100313 ],
  1199. [ 0, 3434, 0 ],
  1200. [ 3432, 0, 0 ],
  1201. ];
  1202. }
  1203. /**
  1204. * @test arithmeticGeometricMean negative
  1205. */
  1206. public function testArithmeticGeometricMeanNegativeNAN()
  1207. {
  1208. $this->assertNan(Average::arithmeticGeometricMean(-32, 45));
  1209. $this->assertNan(Average::arithmeticGeometricMean(32, -45));
  1210. $this->assertNan(Average::agm(-32, 45));
  1211. $this->assertNan(Average::agm(32, -45));
  1212. }
  1213. /**
  1214. * @test logarithmicMean
  1215. * @dataProvider dataProviderForArithmeticLogarithmicMean
  1216. * @param float $x
  1217. * @param float $y
  1218. * @param float $expectedMean
  1219. */
  1220. public function testLogarithmicMean(float $x, float $y, float $expectedMean)
  1221. {
  1222. // When
  1223. $mean = Average::logarithmicMean($x, $y);
  1224. // Then
  1225. $this->assertEqualsWithDelta($expectedMean, $mean, 0.01);
  1226. }
  1227. /**
  1228. * @return array [x, y, mean]
  1229. */
  1230. public function dataProviderForArithmeticLogarithmicMean(): array
  1231. {
  1232. return [
  1233. [ 0, 0, 0 ],
  1234. [ 5, 5, 5 ],
  1235. [ 45, 55, 49.83 ],
  1236. [ 70, 30, 47.21 ],
  1237. [ 339.78, 41.03, 141.32 ],
  1238. [ 349.76, 31.05, 131.61 ],
  1239. ];
  1240. }
  1241. /**
  1242. * @test heronianMean
  1243. * @dataProvider dataProviderForHeronianMean
  1244. * @param float $A
  1245. * @param float $B
  1246. * @param float $expected
  1247. */
  1248. public function testHeronianMean(float $A, float $B, float $expected)
  1249. {
  1250. // When
  1251. $H = Average::heronianMean($A, $B);
  1252. // Then
  1253. $this->assertEqualsWithDelta($expected, $H, 0.00001);
  1254. }
  1255. /**
  1256. * @return array [A, B, H]
  1257. */
  1258. public function dataProviderForHeronianMean(): array
  1259. {
  1260. return [
  1261. [ 4, 5, 4.490711985 ],
  1262. [ 12, 50, 28.8316324759 ],
  1263. ];
  1264. }
  1265. /**
  1266. * @test identricMean
  1267. * @dataProvider dataProviderForIdentricMean
  1268. * @param float $x
  1269. * @param float $y
  1270. * @param float $expectedMean
  1271. * @throws \Exception
  1272. */
  1273. public function testIdentricMean(float $x, float $y, float $expectedMean)
  1274. {
  1275. // When
  1276. $mean = Average::identricMean($x, $y);
  1277. // Then
  1278. $this->assertEqualsWithDelta($expectedMean, $mean, 0.001);
  1279. }
  1280. /**
  1281. * @return array [x, y, mean]
  1282. */
  1283. public function dataProviderForIdentricMean(): array
  1284. {
  1285. return [
  1286. [ 5, 5, 5 ],
  1287. [ 5, 6, 5.49241062633 ],
  1288. [ 6, 5, 5.49241062633 ],
  1289. [ 12, 3, 7.00766654296 ],
  1290. [ 3, 12, 7.00766654296 ],
  1291. ];
  1292. }
  1293. /**
  1294. * @test identricMean throws an \Exception for a negative value
  1295. * @throws \Exception
  1296. */
  1297. public function testIdentricMeanExceptionNegativeValue()
  1298. {
  1299. // Given
  1300. $x = -2;
  1301. $y = 5;
  1302. // Then
  1303. $this->expectException(Exception\OutOfBoundsException::class);
  1304. // When
  1305. Average::identricMean($x, $y);
  1306. }
  1307. /**
  1308. * @test describe
  1309. * @throws \Exception
  1310. */
  1311. public function testDescribe()
  1312. {
  1313. // Given
  1314. $numbers = [13, 18, 13, 14, 13, 16, 14, 21, 13];
  1315. // When
  1316. $averages = Average::describe($numbers);
  1317. // Then
  1318. $this->assertTrue(\is_array($averages));
  1319. $this->assertArrayHasKey('mean', $averages);
  1320. $this->assertArrayHasKey('median', $averages);
  1321. $this->assertArrayHasKey('mode', $averages);
  1322. $this->assertArrayHasKey('geometric_mean', $averages);
  1323. $this->assertArrayHasKey('harmonic_mean', $averages);
  1324. $this->assertArrayHasKey('contraharmonic_mean', $averages);
  1325. $this->assertArrayHasKey('quadratic_mean', $averages);
  1326. $this->assertArrayHasKey('trimean', $averages);
  1327. $this->assertArrayHasKey('iqm', $averages);
  1328. $this->assertArrayHasKey('cubic_mean', $averages);
  1329. $this->assertTrue(\is_numeric($averages['mean']));
  1330. $this->assertTrue(\is_numeric($averages['median']));
  1331. $this->assertTrue(\is_array($averages['mode']));
  1332. $this->assertTrue(\is_numeric($averages['geometric_mean']));
  1333. $this->assertTrue(\is_numeric($averages['harmonic_mean']));
  1334. $this->assertTrue(\is_numeric($averages['contraharmonic_mean']));
  1335. $this->assertTrue(\is_numeric($averages['quadratic_mean']));
  1336. $this->assertTrue(\is_numeric($averages['trimean']));
  1337. $this->assertTrue(\is_numeric($averages['iqm']));
  1338. $this->assertTrue(\is_numeric($averages['cubic_mean']));
  1339. }
  1340. }