Skip to content

Commit 5f4cbda

Browse files
committed
Implementation of MEDIAN() to calculate the median of a data sample in statistics.
1 parent b09d795 commit 5f4cbda

File tree

8 files changed

+49
-0
lines changed

8 files changed

+49
-0
lines changed

samples/distro-examples/tests/all.bas

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ print "SQR:" + SQR (x)
217217
print "SQUEEZE:" + SQUEEZE (s)
218218
print "STATMEAN:" + STATMEAN (1,2,3,4,5,6,7,8,9)
219219
print "STATMEANDEV:" + STATMEANDEV (1,2,3,4,5,6,7,8,9)
220+
print "STATMEDIAN:" + STATMEDIAN(1,2,3,4,5,6,7,8,9)
220221
print "STATSPREADP:" + STATSPREADP (1,2,3,4,5,6,7,8,9)
221222
print "STATSPREADS:" + STATSPREADS (1,2,3,4,5,6,7,8,9)
222223
print "STATSTD:" + STATSTD (1,2,3,4,5,6,7,8,9)

samples/distro-examples/tests/output/all.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ SQR:3.50713558335004
200200
SQUEEZE:catsanddogs
201201
STATMEAN:5
202202
STATMEANDEV:2.22222222222222
203+
STATMEDIAN:5
203204
STATSPREADP:6.66666666666667
204205
STATSPREADS:7.5
205206
STATSTD:2.73861278752583

src/common/blib_func.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,6 +2620,7 @@ void cmd_genfunc(long funcCode, var_t *r) {
26202620
//
26212621
//
26222622
case kwSTATMEANDEV:
2623+
case kwSTATMEDIAN:
26232624
case kwSTATSTD:
26242625
case kwSTATSPREADS:
26252626
case kwSTATSPREADP:
@@ -2690,6 +2691,9 @@ void cmd_genfunc(long funcCode, var_t *r) {
26902691
case kwSTATMEANDEV:
26912692
r->v.n = statmeandev(dar, tcount);
26922693
break;
2694+
case kwSTATMEDIAN:
2695+
r->v.n = statmedian(dar, tcount);
2696+
break;
26932697
case kwSTATSTD:
26942698
r->v.n = statstd(dar, tcount);
26952699
break;

src/common/blib_math.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,35 @@ var_num_t statmeandev(var_num_t *e, int count) {
232232
return sum / count;
233233
}
234234

235+
//
236+
// compare function for median calculation
237+
//
238+
int median_compare (const void * a, const void * b) {
239+
var_num_t fa = *(var_num_t*) a;
240+
var_num_t fb = *(var_num_t*) b;
241+
return (fa > fb) - (fa < fb);
242+
}
243+
244+
//
245+
// Median
246+
//
247+
// Median is calculated using quicksort with a complexity of O(n log n).
248+
// Faster approch would be to implement i.e. quickselect with a
249+
// complexity of O(n).
250+
//
251+
var_num_t statmedian(var_num_t *e, int count) {
252+
if (count == 0) {
253+
return 0;
254+
}
255+
256+
qsort(e, count, sizeof(var_num_t), median_compare);
257+
258+
if (count % 2 == 0)
259+
return (e[count/2] + e[count/2 - 1]) / 2;
260+
else
261+
return e[count/2];
262+
}
263+
235264
//
236265
// Standard deviation
237266
//

src/common/blib_math.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ var_num_t mat_determ(var_num_t *a, int n, double toler);
7575
*/
7676
var_num_t statmeandev(var_num_t *e, int count);
7777

78+
/**
79+
* @ingroup math
80+
*
81+
* Median
82+
*
83+
* @param e array with numbers
84+
* @param count number of elements of e
85+
* @return the median
86+
*/
87+
var_num_t statmedian(var_num_t *e, int count);
88+
7889
/**
7990
* @ingroup math
8091
*

src/common/eval.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,7 @@ static inline void eval_callf(var_t *r) {
11751175
case kwSUMSV:
11761176
case kwSTATMEAN:
11771177
case kwSTATMEANDEV:
1178+
case kwSTATMEDIAN:
11781179
case kwSTATSTD:
11791180
case kwSTATSPREADS:
11801181
case kwSTATSPREADP:

src/common/kw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ enum func_keywords {
348348
kwSUM,
349349
kwSUMSV,
350350
kwSTATMEAN,
351+
kwSTATMEDIAN,
351352
kwSTATSTD,
352353
kwSTATMEANDEV,
353354
kwSTATSPREADS,

src/languages/keywords.en.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ struct func_keyword_s func_table[] = {
288288
{ "SUM", kwSUM },
289289
{ "SUMSQ", kwSUMSV },
290290
{ "STATMEAN", kwSTATMEAN },
291+
{ "STATMEDIAN", kwSTATMEDIAN},
291292
{ "STATSTD", kwSTATSTD},
292293
{ "STATMEANDEV", kwSTATMEANDEV },
293294
{ "STATSPREADS", kwSTATSPREADS },

0 commit comments

Comments
 (0)