.de pg
.sp
..
.he 'MEDIAN''Page %'
.fo 'Steven Hardy'- % -'4th July, 1977'
.ce 2
Finding the median of a list of numbers
=======================================
.pg
The median of a list of numbers is defined as that
element of the list which has as many elements below it as above it, for example:
 	: MEDIAN([7 3 9 2 1 4 8]) =>
 	** 4
.br
Notice that the
.ul
median
is not the same as the
.ul
mean
which is defined as the sum of the numbers divided by the size of the list, that is
 	: MEAN([7 3 9 2 1 4 8]) =>
 	** 4.857
.br
.pg
Clearly, it is easiest to find the median of some numbers if they are
arranged in numerical order, for then the median is merely the middle element, that is:
 	: FUNCTION MEDIAN(LIST);
 	:	MIDDLE(SORT(LIST))
 	: END;
.br
where	: SORT([7 3 9 2 1 4 8]) =>
 	** [1 2 3 4 7 8 9]
.br
and	: MIDDLE([1 2 3 4 7 8 9]) =>
 	** 4
.pg
We tackle the easier of these two subsiduary functions ('subroutines`)
first, ie MIDDLE.
This function can be approximated to:
 	: FUNCTION MIDDLE(LIST);
 	:	NTHOF(LENGTH(LIST)/2, LIST)
 	: END;
.br
where NTHOF takes a number and a list and returns the corresponding element
of the list, that is:
 	: NTHOF(1, [1 2 3 4 7 8 9]) =>
 	** 1
 	: NTHOF(2, [1 2 3 4 7 8 9]) =>
 	** 2
 	: NTHOF(3, [1 2 3 4 7 8 9]) =>
 	** 3
 	: NTHOF(4, [1 2 3 4 7 8 9]) =>
 	** 4
.br
We defer writing NTHOF until definition of MIDDLE is complete - the version shown above
doesn't work properly since:
 	: VARS LIST; [1 2 3 4 7 8 9] -> LIST;
 	: LENGTH(LIST) =>
 	** 7
 	: LENGTH(LIST) / 2 =>
 	** 3
.br
(integer division ignores remainders)
 	: NTHOF(3, LIST) =>
 	** 2
.br
ie	: MIDDLE(LIST) =>
 	** 3
.br
We could modify our definition of MIDDLE, thus:
 	: FUNCTION MIDDLE(LIST);
 	:	NTHOF(LENGTH(LIST)/2+1, LIST)
 	: END;
.br
Unfortunately, our definition still doesn't work on lists with an even number
of components:
 	: MIDDLE([1 2 3 4]) =>
 	** 3
.br
since	: VARS LIST; [1 2 3 4] -> LIST;
 	: LENGTH(LIST) =>
 	** 4
 	: LENGTH(LIST)/2+1 =>
 	** 3
 	: NTHOF(3, LIST) =>
 	** 3
.br
Perhaps we ought to vary MIDDLE's action if it is given a list
with an even number of numbers in it:
 	: FUNCTION MIDDLE(LIST);
 	:	VARS N; LENGTH(LIST) -> N;
 	:	IF ISEVEN(N) THEN
 	:		...
 	:	ELSE
 	:		NTHOF(N/2+1,LIST)
 	:	CLOSE
 	: END;
.br
What should go in place of the dots?
How about code to compute the average of the middle two elements, that is:
 	: (NTHOF(..., LIST) + NTHOF(... + 1, LIST)) / 2
.br
What should now go in place of the dots?
NB - notice that:
 	: A + B / 2
.br
is NOT the same as:
 	: (A + B) / 2
.br
Can you tell the difference?
.pg
Most of the functions  used in the definition of MEDIAN (ie SORT, ISEVEN etc) are
defined in the POP11 system library. nevertheless it is sensible to try writing them
yourself once you have completed a definition of MEDIAN which is to your taste.
Here are some hints on how to write these functions:
.pg
NTHOF -- try the following function schema:
 	: FUNCTION NTHOF(NUMBER, LIST);
 	:	IF <the number is one> THEN
 	:		<the first element of the list>
 	:	ELSE
 	:		NTHOF(<one less than the number>,
 	:			<all but the first of the list>)
 	:	CLOSE
 	: END;
.sp
ISEVEN - see the sections on "/" and "//" in the SVSVARS demo.
.sp
SORT - See the SORT demo.
