Write a program to find the   median   value of a vector of floating-point numbers.

Task
Averages/Median
You are encouraged to solve this task according to the task description, using any language you may know.
Task

The program need not handle the case where the vector is empty, but must handle the case where there are an even number of elements.   In that case, return the average of the two middle values.

There are several approaches to this.   One is to sort the elements, and then pick the element(s) in the middle.

Sorting would take at least   O(n logn).   Another approach would be to build a priority queue from the elements, and then extract half of the elements to get to the middle element(s).   This would also take   O(n logn).   The best solution is to use the   selection algorithm   to find the median in   O(n)   time.

See also

Quickselect_algorithm


11l

Translation of: Python
F median(aray)
   V srtd = sorted(aray)
   V alen = srtd.len
   R 0.5 * (srtd[(alen - 1) I/ 2] + srtd[alen I/ 2])

print(median([4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]))
print(median([4.1, 7.2, 1.7, 9.3, 4.4, 3.2]))
Output:
4.4
4.25

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
or android 64 bits with application Termux
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program averageMed64.s   */
/* use quickselect look pseudo code in wikipedia  quickselect */

/************************************/
/* Constantes                       */
/************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc" 

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResultValue:        .asciz "Result  : "
szCarriageReturn:         .asciz "\n"
     
.align 4
TableNumber:              .double 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2
.equ NBELEMENTS,      (. - TableNumber) / 8
TableNumber2:	          .double 4.1, 7.2, 1.7, 9.3, 4.4, 3.2
.equ NBELEMENTS2,      (. - TableNumber2) / 8
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:             .skip 24
sZoneConv1:            .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                    // entry of program 
    ldr x0,qAdrTableNumber               // address number table
    mov x1,#0                            // index first item
    mov x2,#NBELEMENTS -1                // index last item 
    bl searchMedian
    ldr x0,qAdrTableNumber2              // address number table 2
    mov x1,#0                            // index first item
    mov x2,#NBELEMENTS2 -1               // index last item 
    bl searchMedian

100:                                     // standard end of the program 
    mov x0, #0                           // return code
    mov x8, #EXIT                        // request to exit program
    svc #0                               // perform the system call
 
qAdrszCarriageReturn:     .quad  szCarriageReturn
qAdrTableNumber:          .quad  TableNumber
qAdrTableNumber2:         .quad  TableNumber2
qAdrsZoneConv:            .quad  sZoneConv
qAdrszMessResultValue:    .quad  szMessResultValue
/***************************************************/
/*   search median term in float array                       */
/***************************************************/
/* x0 contains the address of table */
/* x1 contains index of first item  */
/* x2 contains index of last item   */
searchMedian:
    stp x1,lr,[sp,-16]!            // save  registers  TODO: à revoir génération
    stp x2,x3,[sp,-16]!            // save  registers
    stp x4,x5,[sp,-16]!            // save  registers

    mov x19,x0                     // save array address
    add x4,x1,x2
    add x4,x4,#1                   // sum numbers terms
    tst x4,#1                      // odd ?
    bne 1f
    lsr x3,x4,#1                   // compute median index
    bl select                      // call selection
    fmov d0,x0                     // save first result
    sub x3,x3,#1                   // second term
    mov x0,x19
    bl select                      // call selection
    fmov d1,x0                     // save 2ieme résult
    fadd d0,d0,d1                  // compute average two résults
    mov x0,#2
    fmov d1,x0
    scvtf d1,d1                    // conversion integer -> float
    fdiv  d0,d0,d1
    b 2f
1:                                 // even
    lsr x3,x4,#1
    bl select                      // call selection
    fmov d0,x0
2:
    ldr x0,qAdrsZoneConv           // conversion float in decimal string 
    bl convertirFloat
    mov x0,#3                      // and display result
    ldr x1,qAdrszMessResultValue
    ldr x2,qAdrsZoneConv
    ldr x3,qAdrszCarriageReturn
    bl displayStrings  
100:                               // end function
 
    ldp x4,x5,[sp],16              // restaur  2 registers
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret 

/***************************************************/
/*   Appel récursif selection                      */
/***************************************************/
/* x0 contains the address of table */
/* x1 contains index of first item  */
/* x2 contains index of last item   */
/* x3 contains search index */
select:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    stp x4,x5,[sp,-16]!            // save  registers
    stp x6,x7,[sp,-16]!            // save  registers
    mov x6,x3                      // save search index
    cmp x1,x2                      // first = last ? 
    bne 1f
    ldr x0,[x0,x1,lsl #3]          // return value of first index
    b 100f                         // yes -> end
1:
    add x3,x1,x2
    lsr x3,x3,#1                   // compute median pivot 
    mov x4,x0                      // save x0
    mov x5,x2                      // save x2
    bl partition                   // cutting.quado 2 parts
    cmp x6,x0                      // pivot is ok ?
    bne 2f
    ldr x0,[x4,x0,lsl #3]          // yes -> return value
    b 100f
 2:
    bgt 3f
    sub x2,x0,#1                   // index partition  - 1 
    mov x0,x4                      // array address
    mov x3,x6                      // search index
    bl select                      // select lower part
    b 100f
3:
    add x1,x0,#1                   // index begin = index partition + 1
    mov x0,x4                      // array address
    mov x2,x5                      // last item
    mov x3,x6                      // search index
    bl select                      // select higter part
 
 100:                              // end function
    ldp x6,x7,[sp],16              // restaur  2 registers
    ldp x4,x5,[sp],16              // restaur  2 registers
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/******************************************************************/
/*      Partition table elements                                */ 
/******************************************************************/
/* x0 contains the address of table */
/* x1 contains index of first item  */
/* x2 contains index of last item   */
/* x3 contains index of pivot */
partition:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    stp x4,x5,[sp,-16]!            // save  registers
    stp x6,x7,[sp,-16]!            // save  registers
    ldr x4,[x0,x3,lsl #3]          // load value of pivot
    ldr x5,[x0,x2,lsl #3]          // load value last index
    str x5,[x0,x3,lsl #3]          // swap value of pivot
    str x4,[x0,x2,lsl #3]          // and value last index
    mov x3,x1                      // init with first index
1:                                 // begin loop
    ldr x6,[x0,x3,lsl #3]          // load value
    cmp x6,x4                      // compare loop value and pivot value
    bge 2f
    ldr x5,[x0,x1,lsl #3]          // if < swap value table
    str x6,[x0,x1,lsl #3]
    str x5,[x0,x3,lsl #3]
    add x1,x1,#1                   // and increment index 1
2:
    add x3,x3,#1                   // increment index 2
    cmp x3,x2                      // end ?
    blt 1b                         // no loop
    ldr x5,[x0,x1,lsl #3]          // swap value
    str x4,[x0,x1,lsl #3]
    str x5,[x0,x2,lsl #3]
    mov x0,x1                      // return index partition
100:
    ldp x6,x7,[sp],16              // restaur  2 registers
    ldp x4,x5,[sp],16              // restaur  2 registers
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
    
 /***************************************************/
/*   display multi strings                         */
/*   new version 24/05/2023                        */
/***************************************************/
/* x0  contains number strings address */
/* x1 address string1 */
/* x2 address string2 */
/* x3 address string3 */
/* x4 address string4 */
/* x5 address string5 */
/* x6 address string5 */
/* x7 address string6 */
displayStrings:            // INFO:  displayStrings
    stp x8,lr,[sp,-16]!    // save  registers 
    stp x2,fp,[sp,-16]!    // save  registers 
    add fp,sp,#32          // save paraméters address (4 registers saved * 8 bytes)
    mov x8,x0              // save strings number
    cmp x8,#0              // 0 string -> end
    ble 100f
    mov x0,x1              // string 1
    bl affichageMess
    cmp x8,#1              // number > 1
    ble 100f
    mov x0,x2
    bl affichageMess
    cmp x8,#2
    ble 100f
    mov x0,x3
    bl affichageMess
    cmp x8,#3
    ble 100f
    mov x0,x4
    bl affichageMess
    cmp x8,#4
    ble 100f
    mov x0,x5
    bl affichageMess
    cmp x8,#5
    ble 100f
    mov x0,x6
    bl affichageMess
    cmp x8,#6
    ble 100f
    mov x0,x7
    bl affichageMess
    
100:
    ldp x2,fp,[sp],16        // restaur  registers 
    ldp x8,lr,[sp],16        // restaur  registers
    ret
/******************************************************************/
/*     Conversion Float                                            */ 
/******************************************************************/
/* d0 contains Float */
/* x0 contains address conversion area  mini 20 charactèrs */
/* x0 return result length */
/* see https://blog.benoitblanchon.fr/lightweight-float-to-string/ */
convertirFloat:
    stp x1,lr,[sp,-16]!       // save  registres
    stp x2,x3,[sp,-16]!       // save  registres
    stp x4,x5,[sp,-16]!       // save  registres
    stp x6,x7,[sp,-16]!       // save  registres
    stp x8,x9,[sp,-16]!       // save  registres
    stp d1,d2,[sp,-16]!       // save  registres
    mov x6,x0                 // save area address
    fmov x0,d0
    mov x8,#0                 // result length
    mov x3,#'+'
    strb w3,[x6]              // signe + forcing
    mov x2,x0
    tbz x2,63,1f
    mov x2,1
    lsl x2,x2,63
    bic x0,x0,x2
    mov x3,#'-'               // sign -
    strb w3,[x6]
1:
    adds x8,x8,#1             // next position
    cmp x0,#0                 // case 0 positive or negative
    bne 2f
    mov x3,#'0'
    strb w3,[x6,x8]           // store character 0
    adds x8,x8,#1
    strb wzr,[x6,x8]          // store 0 final
    mov x0,x8                 // return length
    b 100f
2: 
    ldr x2,iMaskExposant
    mov x1,x0
    and x1,x1,x2              // exposant
    cmp x1,x2
    bne 4f
    tbz x0,51,3f              // test bit 51 to zéro 
    mov x2,#'N'               // case Nan. store byte  no possible store integer 
    strb w2,[x6]              // area no aligned
    mov x2,#'a'
    strb w2,[x6,#1] 
    mov x2,#'n'
    strb w2,[x6,#2] 
    mov x2,#0                  // 0 final
    strb w2,[x6,#3] 
    mov x0,#3
    b 100f
3:                             // case infini positive or négative
    mov x2,#'I'
    strb w2,[x6,x8] 
    adds x8,x8,#1
    mov x2,#'n'
    strb w2,[x6,x8] 
    adds x8,x8,#1
    mov x2,#'f'
    strb w2,[x6,x8] 
    adds x8,x8,#1
    mov x2,#0
    strb w2,[x6,x8]
    mov x0,x8
    b 100f
4:
    bl normaliserFloat
    mov x5,x0                // save exposant
    fcvtzu d2,d0
    fmov x0,d2               // part integer
    scvtf d1,d2              // conversion float
    fsub d1,d0,d1            // extraction part fractional
    ldr d2,dConst1
    fmul d1,d2,d1            // to crop it in full
    fcvtzu d1,d1             // convertion integer
    fmov x4,d1               // fract value
                             // conversion part integer to x0
    mov x2,x6                // save address begin area
    adds x6,x6,x8
    mov x1,x6
    bl conversion10
    add x6,x6,x0
    mov x3,#','
    strb w3,[x6]
    adds x6,x6,#1
 
    mov x0,x4                // conversion part fractionnaire
    mov x1,x6
    bl conversion10SP
    add x6,x6,x0
    sub x6,x6,#1
                             //  remove trailing zeros
5:
    ldrb w0,[x6]
    cmp w0,#'0'
    bne 6f
    sub x6,x6,#1
    b 5b
6:
    cmp w0,#','
    bne 7f
    sub x6,x6,#1
7:  
    cmp x5,#0                  // if exposant = 0 no display
    bne 8f
    add x6,x6,#1
    b 10f
8:
    add x6,x6,#1
    mov x3,#'E'
    strb w3,[x6]
    add x6,x6,#1
    mov x0,x5                  // conversion exposant
    mov x3,x0
    tbz x3,63,9f               // exposant negative ?
    neg x0,x0
    mov x3,#'-'
    strb w3,[x6]
    adds x6,x6,#1
9:
    mov x1,x6
    bl conversion10
    add x6,x6,x0
10:
    strb wzr,[x6]              // store 0 final
    adds x6,x6,#1
    mov x0,x6
    subs x0,x0,x2              // retour de la longueur de la zone
    subs x0,x0,#1              // sans le 0 final

100:
    ldp d1,d2,[sp],16          // restaur  registres
    ldp x8,x9,[sp],16          // restaur  registres
    ldp x6,x7,[sp],16          // restaur  registres
    ldp x4,x5,[sp],16          // restaur  registres
    ldp x2,x3,[sp],16          // restaur  registres
    ldp x1,lr,[sp],16          // restaur registres
    ret
    
iMaskExposant:            .quad 0x7FF<<52
dConst1:                  .double 0f1E17

/***************************************************/
/*   normaliser float                              */
/***************************************************/
/* x0 contain float value (always positive value and <> Nan) */
/* d0 return new value */
/* x0 return exposant */
normaliserFloat:
    stp x1,lr,[sp,-16]!       // save  registers
    fmov d0,x0                // value float
    mov x0,#0                 // exposant
    ldr d1,dConstE7           // no normalisation for value  < 1E7
    fcmp d0,d1
    blo 10f                   // if d0 < dConstE7
    
    ldr d1,dConstE256
    fcmp d0,d1
    blo 1f
    fdiv d0,d0,d1
    adds x0,x0,#256
1:
    
    ldr d1,dConstE128
    fcmp d0,d1
    blo 1f
    fdiv d0,d0,d1
    adds x0,x0,#128
1:
    ldr d1,dConstE64
    fcmp d0,d1
    blo 1f
    fdiv d0,d0,d1
    adds x0,x0,#64
1:
    ldr d1,dConstE32
    fcmp d0,d1
    blo 1f
    fdiv d0,d0,d1
    adds x0,x0,#32
1:
    ldr d1,dConstE16
    fcmp d0,d1
    blo 2f
    fdiv d0,d0,d1
    adds x0,x0,#16
2:
    ldr d1,dConstE8
    fcmp d0,d1
    blo 3f
    fdiv d0,d0,d1
    adds x0,x0,#8
3:
    ldr d1,dConstE4
    fcmp d0,d1
    blo 4f
    fdiv d0,d0,d1
    adds x0,x0,#4
4:
    ldr d1,dConstE2
    fcmp d0,d1
    blo 5f
    fdiv d0,d0,d1
    adds x0,x0,#2
5:
    ldr d1,dConstE1
    fcmp d0,d1
    blo 10f
    fdiv d0,d0,d1
    adds x0,x0,#1

10:
    ldr d1,dConstME5        // pas de normalisation pour les valeurs > 1E-5
    fcmp d0,d1
    bhi 100f                 // fin
    
    ldr d1,dConstME255
    fcmp d0,d1
    bhi 11f
    ldr d1,dConstE256

    fmul d0,d0,d1
    subs x0,x0,#256
11:
    
    ldr d1,dConstME127
    fcmp d0,d1
    bhi 11f
    ldr d1,dConstE128

    fmul d0,d0,d1
    subs x0,x0,#128
11:
    
    ldr d1,dConstME63
    fcmp d0,d1
    bhi 11f
    ldr d1,dConstE64

    fmul d0,d0,d1
    subs x0,x0,#64
11:
   
    ldr d1,dConstME31
    fcmp d0,d1
    bhi 11f
    ldr d1,dConstE32

    fmul d0,d0,d1
    subs x0,x0,#32
11:
    ldr d1,dConstME15
    fcmp d0,d1
    bhi 12f
    ldr d1,dConstE16
    fmul d0,d0,d1
    subs x0,x0,#16
12:
    ldr d1,dConstME7
    fcmp d0,d1
    bhi 13f
    ldr d1,dConstE8
    fmul d0,d0,d1
    subs x0,x0,#8
13:
    ldr d1,dConstME3
    fcmp d0,d1
    bhi 14f
    ldr d1,dConstE4
    fmul d0,d0,d1
    subs x0,x0,#4
14:
    ldr d1,dConstME1
    fcmp d0,d1
    bhi 15f
    ldr d1,dConstE2
    fmul d0,d0,d1
    subs x0,x0,#2
15:
    ldr d1,dConstE0
    fcmp d0,d1
    bhi 100f
    ldr d1,dConstE1
    fmul d0,d0,d1
    subs x0,x0,#1

100:                       // fin standard de la fonction
    ldp x1,lr,[sp],16           // restaur registres
    ret
.align 2
dConstE7:             .double 0f1E7
dConstE256:           .double 0f1E256
dConstE128:           .double 0f1E128
dConstE64:            .double 0f1E64
dConstE32:            .double 0f1E32
dConstE16:            .double 0f1E16
dConstE8:             .double 0f1E8
dConstE4:             .double 0f1E4
dConstE2:             .double 0f1E2
dConstE1:             .double 0f1E1
dConstME5:            .double 0f1E-5
dConstME255:          .double 0f1E-255
dConstME127:          .double 0f1E-127
dConstME63:           .double 0f1E-63
dConstME31:           .double 0f1E-31
dConstME15:           .double 0f1E-15
dConstME7:            .double 0f1E-7
dConstME3:            .double 0f1E-3
dConstME1:            .double 0f1E-1
dConstE0:             .double 0f1E0

/******************************************************************/
/*     Décimal Conversion                                         */ 
/******************************************************************/
/* x0 contain value et x1 address conversion area   */
conversion10SP:
    stp x1,lr,[sp,-16]!         // save  registers
    stp x2,x3,[sp,-16]!         // save  registers
    stp x4,x5,[sp,-16]!         // save  registers
    mov x5,x1
    mov x4,#16
    mov x2,x0
    mov x1,#10                  // décimal conversion
1:                              // conversion loop
    mov x0,x2                   // copy begin number or quotient
    udiv x2,x0,x1               // division by 10
    msub x3,x1,x2,x0            // compute remainder
    add x3,x3,#48               // compute digit    
    strb w3,[x5,x4]             // store byte address area (x5) + offset (x4)
    subs x4,x4,#1               // position precedente
    bge 1b
    strb wzr,[x5,16]            // 0 final
100:    
    ldp x4,x5,[sp],16           // restaur  registers
    ldp x2,x3,[sp],16           // restaur  registers
    ldp x1,lr,[sp],16           // restaur registers
    ret

/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeARM64.inc"
Output:
Result  : +4,4
Result  : +4,25

Action!

INCLUDE "H6:REALMATH.ACT"

DEFINE PTR="CARD"

PROC Sort(PTR ARRAY a INT count)
  INT i,j,minpos
  REAL POINTER tmp

  FOR i=0 TO count-2
  DO
    minpos=i
    FOR j=i+1 TO count-1
    DO
      IF RealGreaterOrEqual(a(minpos),a(j)) THEN
        minpos=j
      FI
    OD
    
    IF minpos#i THEN
      tmp=a(i)
      a(i)=a(minpos)
      a(minpos)=tmp
    FI
  OD
RETURN

PROC Median(PTR ARRAY a INT count REAL POINTER res)
  IF count=0 THEN Break() FI
  Sort(a,count)
  IF (count&1)=0 THEN
    RealAdd(a(count RSH 1-1),a(count RSH 1),res)
    RealMult(res,half,res)
  ELSE
    RealAssign(a(count RSH 1),res)
  FI
RETURN

PROC Test(PTR ARRAY a INT count)
  INT i
  REAL res

  FOR i=0 TO count-1
  DO
    PrintR(a(i)) Put(32)
  OD
  Median(a,count,res)
  Print("-> ")
  PrintRE(res)
RETURN

PROC Main()
  PTR ARRAY a(8)
  REAL r1,r2,r3,r4,r5,r6,r7,r8
  BYTE i
  
  Put(125) PutE() ;clear the screen
  MathInit()
  ValR("3.2",r1)  ValR("-4.1",r2)
  ValR("0.6",r3)  ValR("9.8",r4)
  ValR("5.1",r5)  ValR("-1.4",r6)
  ValR("0.3",r7) ValR("2.2",r8)
  FOR i=1 TO 8
  DO
    a(0)=r1 a(1)=r2 a(2)=r3 a(3)=r4
    a(4)=r5 a(5)=r6 a(6)=r7 a(7)=r8
    Test(a,i)
  OD
RETURN
Output:

Screenshot from Atari 8-bit computer

3.2 -> 3.2
3.2 -4.1 -> -0.45
3.2 -4.1 .6 -> .6
3.2 -4.1 .6 9.8 -> 1.9
3.2 -4.1 .6 9.8 5.1 -> 3.2
3.2 -4.1 .6 9.8 5.1 -1.4 -> 1.9
3.2 -4.1 .6 9.8 5.1 -1.4 .3 -> .6
3.2 -4.1 .6 9.8 5.1 -1.4 .3 2.2 -> 1.4

Ada

with Ada.Text_IO, Ada.Float_Text_IO;

procedure FindMedian is

    f: array(1..10) of float := ( 4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5 );
    min_idx: integer;
    min_val, median_val, swap: float;

begin
    for i in f'range loop
        min_idx := i;
        min_val := f(i);
        for j in i+1 .. f'last loop
            if f(j) < min_val then
                min_idx := j;
                min_val := f(j);
            end if;                
        end loop;
        swap := f(i); f(i) := f(min_idx); f(min_idx) := swap;
    end loop;      

    if f'length mod 2 /= 0 then
        median_val := f( f'length/2+1 );
    else
        median_val := ( f(f'length/2) + f(f'length/2+1) ) / 2.0;
    end if;
    
    Ada.Text_IO.Put( "Median value: " );
    Ada.Float_Text_IO.Put( median_val );
    Ada.Text_IO.New_line;    
end FindMedian;

ALGOL 68

Translation of: C
INT max_elements = 1000000;
 
# Return the k-th smallest item in array x of length len #
PROC quick_select = (INT k, REF[]REAL x) REAL:
   BEGIN

      PROC swap = (INT a, b) VOID:
         BEGIN 
	    REAL t = x[a];
	    x[a] := x[b]; x[b] := t
         END;

      INT left := 1, right := UPB x;
      INT pos, i;
      REAL pivot;

      WHILE left < right DO 
	 pivot := x[k];
	 swap (k, right);
	 pos := left;
	 FOR i FROM left TO right DO
	    IF x[i] < pivot THEN 
	       swap (i, pos);
	       pos +:= 1
	    FI
	 OD;
	 swap (right, pos);
	 IF pos = k THEN break FI;
	 IF pos < k THEN left := pos + 1
	 ELSE right := pos - 1
         FI
      OD;
break:
      SKIP;
      x[k]
   END;
 
 # Initialize random length REAL array with random doubles #
 INT length = ENTIER (next random * max_elements);
 [length]REAL x;
 FOR i TO length DO 
    x[i] := (next random * 1e6 - 0.5e6)
 OD;

 REAL median :=
    IF NOT ODD length THEN
       # Even number of elements, median is average of middle two #
       (quick_select (length % 2, x) + quick_select(length % 2 - 1, x)) / 2
    ELSE
       # select middle element #
       quick_select(length % 2, x)
    FI;

 # Sanity testing of median #
 INT less := 0, more := 0, eq := 0;
 FOR i TO length DO 
    IF x[i] < median THEN less +:= 1
    ELIF x[i] > median THEN more +:= 1
    ELSE eq +:= 1
    FI
 OD;
 print (("length: ", whole (length,0), new line, "median: ", median, new line,
	 "<: ", whole (less,0), new line,
	 ">: ", whole (more, 0), new line,
	 "=: ", whole (eq, 0), new line))

Sample output:

length: 97738
median: -2.52550126608709e  +3
<: 48868
>: 48870
=: 0

Amazing Hopper

Translation of: BaCon
#include <basico.h>

#proto  cálculodemediana(_X_)
#synon  _cálculodemediana   obtenermedianade

algoritmo

    decimales '2'
    matrices 'a,b'
    '4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2', enlistar en 'a'
    '4.1, 7.2, 1.7, 9.3, 4.4, 3.2', enlistar en 'b'
    
    arr.ordenar 'a'
    arr.ordenar 'b'
    "A=",a,NL,"Median: ", obtener mediana de 'a', NL
    "B=",b,NL,"Median: ", obtener mediana de 'b', NL
    finalmente imprime

terminar

subrutinas

cálculo de mediana (x)

    dx=0
    filas de 'x' ---copiar en 'dx'---
    calcular si ( es par?, #( (x[ (dx/2) ]+x[ (dx/2)+1 ])/2 ),\
                           #( x[ dx/2+1 ] ) )
retornar
Output:
A=1.70,3.20,4.10,4.40,5.60,7.20,9.30
Median: 4.40
B=1.70,3.20,4.10,4.40,7.20,9.30
Median: 4.25

AntLang

AntLang has a built-in median function.

median[list]

APL

median{v[].5×v[¯1+.5×⍴v]+v[.5×⍴v]} ⍝ Assumes ⎕IO←0

First, the input vector ⍵ is sorted with ⍵[⍋⍵] and the result placed in v. If the dimension ⍴v of v is odd, then both ⌈¯1+.5×⍴v and ⌊.5×⍴v give the index of the middle element. If ⍴v is even, ⌈¯1+.5×⍴v and ⌊.5×⍴v give the indices of the two middle-most elements. In either case, the average of the elements at these indices gives the median.

Note that the index origin ⎕IO is assumed zero. To set it to zero use:

⎕IO0

If you prefer an index origin of 1, use this code instead:

⎕IO1
median{v[]  0.5×v[0.5×⍴v]+v[1+0.5×⍴v]}

This code was tested with ngn/apl and Dyalog 12.1. You can try this function online with ngn/apl. Note that ngn/apl currently only supports index origin 0. Examples:

median 1 5 3 6 4 2
3.5

median 1 5 3 2 4
3

median 4.4 2.3 ¯1.7 7.5 6.6 0.0 1.9 8.2 9.3 4.5
4.45

median 4.1 4 1.2 6.235 7868.33
4.1

median 4.1 5.6 7.2 1.7 9.3 4.4 3.2
4.4

median 4.1 7.2 1.7 9.3 4.4 3.2
4.25

Caveats: To keep it simple, no input validation is done. If you input a vector with zero elements (e.g., ⍳0), you get an INDEX ERROR. If you input a vector with 1 element, you get a RANK ERROR. Only (rank 1) numeric vectors of dimension 2 or more are supported. If you input a (rank 2 or more) matrix, you get a RANK ERROR. If you input a string (vector of chars), you get a DOMAIN ERROR:

median ⍳0
INDEX ERROR

median 66.6
RANK ERROR

median (2 2)⍴⍳4 ⍝ 2x2 matrix
RANK ERROR

median 'HELLO'
DOMAIN ERROR

AppleScript

By iteration

set alist to {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}
set med to medi(alist)

on medi(alist)
    
    set temp to {}
    set lcount to count alist
    if lcount is equal to 2 then
        return ((item 1 of alist) + (item 2 of alist)) / 2
    else if lcount is less than 2 then
        return item 1 of alist
    else --if lcount is greater than 2
        set min to findmin(alist)
        set max to findmax(alist)
        repeat with x from 1 to lcount
            if x is not equal to min and x is not equal to max then set end of temp to item x of alist
        end repeat
        set med to medi(temp)
    end if
    return med
    
end medi

on findmin(alist)
    
    set min to 1
    set alength to count every item of alist
    repeat with x from 1 to alength
        if item x of alist is less than item min of alist then set min to x
    end repeat
    return min
    
end findmin

on findmax(alist)
    
    set max to 1
    set alength to count every item of alist
    repeat with x from 1 to alength
        if item x of alist is greater than item max of alist then set max to x
    end repeat
    return max
    
end findmax
Output:
4.5

Composing functionally

Using a quick select algorithm:

Translation of: JavaScript
Translation of: Haskell
-- MEDIAN ---------------------------------------------------------------------

-- median :: [Num] -> Num
on median(xs)
    -- nth :: [Num] -> Int -> Maybe Num
    script nth
        on |λ|(xxs, n)
            if length of xxs > 0 then
                set {x, xs} to uncons(xxs)
                
                script belowX
                    on |λ|(y)
                        y < x
                    end |λ|
                end script
                
                set {ys, zs} to partition(belowX, xs)
                set k to length of ys
                if k = n then
                    x
                else
                    if k > n then
                        |λ|(ys, n)
                    else
                        |λ|(zs, n - k - 1)
                    end if
                end if
            else
                missing value
            end if
        end |λ|
    end script
    
    set n to length of xs
    if n > 0 then
        tell nth
            if n mod 2 = 0 then
                (|λ|(xs, n div 2) + |λ|(xs, (n div 2) - 1)) / 2
            else
                |λ|(xs, n div 2)
            end if
        end tell
    else
        missing value
    end if
end median

-- TEST -----------------------------------------------------------------------
on run
    
    map(median, [¬
        [], ¬
        [5, 3, 4], ¬
        [5, 4, 2, 3], ¬
        [3, 4, 1, -8.4, 7.2, 4, 1, 1.2]])
    
    --> {missing value, 4, 3.5, 2.1}    
end run

-- GENERIC FUNCTIONS ----------------------------------------------------------

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

-- partition :: predicate -> List -> (Matches, nonMatches)
-- partition :: (a -> Bool) -> [a] -> ([a], [a])
on partition(f, xs)
    tell mReturn(f)
        set lst to {{}, {}}
        repeat with x in xs
            set v to contents of x
            set end of item ((|λ|(v) as integer) + 1) of lst to v
        end repeat
    end tell
    {item 2 of lst, item 1 of lst}
end partition

-- uncons :: [a] -> Maybe (a, [a])
on uncons(xs)
    if length of xs > 0 then
        {item 1 of xs, rest of xs}
    else
        missing value
    end if
end uncons
Output:
{missing value, 4, 3.5, 2.1}

Quickselect

-- Return the median value of items l thru r of a list of numbers.
on getMedian(theList, l, r)
    if (theList is {}) then return theList
    
    script o
        property lst : theList's items l thru r -- Copy of the range to be searched.
    end script
    
    set rangeLength to (r - l + 1)
    set m to (rangeLength + 1) div 2 -- Central position in the range copy, or the leftmost of two.        
    set {l, r} to {1, rangeLength} -- Outer partition indices.
    set previousR to r -- Reminder of previous r.
    repeat -- quickselect repeat
        set pivot to o's lst's item ((l + r) div 2)
        set i to l
        set j to r
        repeat until (i > j)
            set lv to o's lst's item i
            repeat while (lv < pivot)
                set i to i + 1
                set lv to o's lst's item i
            end repeat
            
            set rv to o's lst's item j
            repeat while (rv > pivot)
                set j to j - 1
                set rv to o's lst's item j
            end repeat
            
            if (i > j) then
            else
                set o's lst's item i to rv
                set o's lst's item j to lv
                set i to i + 1
                set j to j - 1
            end if
        end repeat
        
        -- If i and j have crossed at m, item m's the median value.
        -- Otherwise reset to partition the partition containing m.
        if (j < m) then
            if (i > m) then exit repeat
            set l to i
        else
            set previousR to r
            set r to j
        end if
    end repeat
    
    set median to item m of o's lst
    -- If the range has an even number of items, find the lowest value to the right of m and average it
    -- with the median just obtained. We only need to search to the end of the range just partitioned —
    -- unless that's where m is, in which case to end of the most recent extent beyond that (if any).
    if (rangeLength mod 2 is 0) then
        set median2 to item i of o's lst
        if (r = m) then set r to previousR
        repeat with i from (i + 1) to r
            set v to item i of o's lst
            if (v < median2) then set median2 to v
        end repeat
        set median to (median + median2) / 2
    end if
    
    return median
end getMedian

-- Demo:
local testList
set testList to {}
repeat with i from 1 to 8
    set end of testList to (random number 500) / 5
end repeat
return {|numbers|:testList, median:getMedian(testList, 1, (count testList))}
Output:
{|numbers|:{71.6, 44.8, 45.8, 28.6, 96.8, 98.4, 42.4, 97.8}, median:58.7}

Partial heap sort

-- Based on the heap sort algorithm ny J.W.J. Williams.
on getMedian(theList, l, r)
    script o
        property lst : theList's items l thru r -- Copy of the range to be searched.
        
        -- Sift a value down into the heap from a given root node.
        on siftDown(siftV, root, endOfHeap)
            set child to root * 2
            repeat until (child comes after endOfHeap)
                set childV to item child of my lst
                if (child comes before endOfHeap) then
                    set child2 to child + 1
                    set child2V to item child2 of my lst
                    if (child2V > childV) then
                        set child to child2
                        set childV to child2V
                    end if
                end if
                
                if (childV > siftV) then
                    set item root of my lst to childV
                    set root to child
                    set child to root * 2
                else
                    exit repeat
                end if
            end repeat
            set item root of my lst to siftV
        end siftDown
    end script
    
    set r to (r - l + 1)
    -- Arrange the sort range into a "heap" with its "top" at the leftmost position.
    repeat with i from (r + 1) div 2 to 1 by -1
        tell o to siftDown(item i of its lst, i, r)
    end repeat
    
    -- Work the heap as if extracting the values that would come after the median when sorted.    
    repeat with endOfHeap from r to (r - (r + 1) div 2 + 2) by -1
        tell o to siftDown(item endOfHeap of its lst, 1, endOfHeap - 1)
    end repeat
    -- Extract the median itself, now at the top of the heap.
    set median to beginning of o's lst
    -- If the range has an even number of items, also get the value that would come before the median
    -- just obtained. By now it's either the second or third item in the heap, so no need to sift for it.
    -- Get the average if it and the median.
    if (r mod 2 is 0) then
        set median2 to item 2 of o's lst
        if ((r > 2) and (item 3 of o's lst > median2)) then set median2 to item 3 of o's lst
        set median to (median + median2) / 2
    end if
    
    return median
end getMedian

-- Demo:
local testList
set testList to {}
repeat with i from 1 to 8
    set end of testList to (random number 500) / 5
end repeat
return {|numbers|:testList, median:getMedian(testList, 1, (count testList))}
Output:
{|numbers|:{28.0, 75.6, 21.4, 51.8, 79.6, 25.0, 95.4, 31.2}, median:41.5}

Applesoft BASIC

 100 REMMEDIAN
 110 K = INT(L/2) : GOSUB 150
 120 R = X(K)
 130 IF L - 2 *  INT (L / 2) THEN R = (R + X(K + 1)) / 2
 140 RETURN

 150 REMQUICK SELECT
 160 LT = 0:RT = L - 1
 170 FOR J = LT TO RT STEP 0
 180     PT = X(K)
 190     P1 = K:P2 = RT: GOSUB 300
 200     P = LT
 210     FOR I = P TO RT - 1
 220         IF X(I) < PT THEN P1 = I:P2 = P: GOSUB 300:P = P + 1
 230     NEXT I
 240     P1 = RT:P2 = P: GOSUB 300
 250     IF P = K THEN  RETURN
 260     IF P < K THEN LT = P + 1
 270     IF P >  = K THEN RT = P - 1
 280 NEXT J
 290 RETURN

 300 REMSWAP
 310 H = X(P1):X(P1) = X(P2)
 320 X(P2) = H: RETURN

Example:

X(0)=4.4 : X(1)=2.3 : X(2)=-1.7 : X(3)=7.5 : X(4)=6.6 : X(5)=0.0 : X(6)=1.9 : X(7)=8.2 : X(8)=9.3 : X(9)=4.5 : X(10)=-11.7
L = 11 : GOSUB 100MEDIAN
? R

Output:

5.95

ARM Assembly

Works with: as version Raspberry Pi
or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program averageMed.s   */
/* use quickselect look pseudo code in wikipedia  quickselect */

/************************************/
/* Constantes                       */
/************************************/
/* for constantes see task include a file in arm assembly */
.include "../constantes.inc"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResultValue:        .asciz "Result  : "
szCarriageReturn:         .asciz "\n"
     
.align 4
TableNumber:              .float 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2
.equ NBELEMENTS,      (. - TableNumber) / 4
TableNumber2:	          .float 4.1, 7.2, 1.7, 9.3, 4.4, 3.2
.equ NBELEMENTS2,      (. - TableNumber2) / 4
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:             .skip 24
sZoneConv1:            .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                    @ entry of program 

    ldr r0,iAdrTableNumber               @ address number table
    mov r1,#0                            @ index first item
    mov r2,#NBELEMENTS -1                @ index last item 
    bl searchMedian
    ldr r0,iAdrTableNumber2               @ address number table 2
    mov r1,#0                             @ index first item
    mov r2,#NBELEMENTS2 -1                @ index last item 
    bl searchMedian

100:                                     @ standard end of the program 
    mov r0, #0                           @ return code
    mov r7, #EXIT                        @ request to exit program
    svc #0                               @ perform the system call
 
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrTableNumber:          .int TableNumber
iAdrTableNumber2:         .int TableNumber2
iAdrsZoneConv:            .int sZoneConv
iAdrszMessResultValue:    .int szMessResultValue
/***************************************************/
/*   search median term in float array                       */
/***************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item  */
/* r2 contains index of last item   */
searchMedian:
    push {r1-r5,lr}                @ save registers
    mov r5,r0                      @ save array address
    add r4,r1,r2
    add r4,r4,#1                   @ sum numbers terms
    tst r4,#1                      @ odd ?
    bne 1f
    lsr r3,r4,#1                   @ compute median index
    bl select                      @ call selection
    vmov s0,r0                     @ save first result
    sub r3,r3,#1                   @ second term
    mov r0,r5
    bl select                      @ call selection
    vmov s1,r0                     @ save 2ieme résult
    vadd.f32 s0,s1                 @ compute average two résults
    mov r0,#2
    vmov s1,r0
    vcvt.f32.u32 s1,s1             @ conversion integer -> float
    vdiv.f32 s0,s0,s1
    b 2f
1:                                 @ even
    lsr r3,r4,#1
    bl select                      @ call selection
    vmov s0,r0
2:
    ldr r0,iAdrsZoneConv           @ conversion float in decimal string 
    bl convertirFloat
    mov r0,#3                      @ and display result
    ldr r1,iAdrszMessResultValue
    ldr r2,iAdrsZoneConv
    ldr r3,iAdrszCarriageReturn
    bl displayStrings  
100:                               @ end function
    pop {r1-r5,pc}                 @ restaur  register
/***************************************************/
/*   Appel récursif selection                      */
/***************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item  */
/* r2 contains index of last item   */
/* r3 contains search index */
/* r0 return final value in float */
/* remark : the final result is a float returned in r0 register */
select:
    push {r1-r6,lr}                @ save registers
    mov r6,r3                      @ save search index
    cmp r1,r2                      @ first = last ? 
    ldreq r0,[r0,r1,lsl #2]        @ return value of first index
    beq 100f                       @ yes -> end
    add r3,r1,r2
    lsr r3,r3,#1                   @ compute median pivot 
    mov r4,r0                      @ save r0
    mov r5,r2                      @ save r2
    bl partition                   @ cutting into 2 parts
    cmp r6,r0                      @ pivot is ok ?
    ldreq r0,[r4,r0,lsl #2]        @ return value
    beq 100f
    bgt 1f
    sub r2,r0,#1                   @ index partition  - 1 
    mov r0,r4                      @ array address
    mov r3,r6                      @ search index
    bl select                      @ select lower part
    b 100f
1:
    add r1,r0,#1                   @ index begin = index partition + 1
    mov r0,r4                      @ array address
    mov r2,r5                      @ last item
    mov r3,r6                      @ search index
    bl select                      @ select higter part
 100:                              @ end function
    pop {r1-r6,pc}                 @ restaur  register
/******************************************************************/
/*      Partition table elements                                */ 
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item  */
/* r2 contains index of last item   */
/* r3 contains index of pivot */
partition:
    push {r1-r6,lr}                                    @ save registers
    ldr r4,[r0,r3,lsl #2]                              @ load value of pivot
    ldr r5,[r0,r2,lsl #2]                              @ load value last index
    str r5,[r0,r3,lsl #2]                              @ swap value of pivot
    str r4,[r0,r2,lsl #2]                              @ and value last index
    mov r3,r1                                          @ init with first index
1:                                                     @ begin loop
    ldr r6,[r0,r3,lsl #2]                              @ load value
    cmp r6,r4                                          @ compare loop value and pivot value
    ldrlt r5,[r0,r1,lsl #2]                            @ if < swap value table
    strlt r6,[r0,r1,lsl #2]
    strlt r5,[r0,r3,lsl #2]
    addlt r1,#1                                        @ and increment index 1
    add r3,#1                                          @ increment index 2
    cmp r3,r2                                          @ end ?
    blt 1b                                             @ no loop
    ldr r5,[r0,r1,lsl #2]                              @ swap value
    str r4,[r0,r1,lsl #2]
    str r5,[r0,r2,lsl #2]
    mov r0,r1                                          @ return index partition
100:
    pop {r1-r6,pc}
    
/***************************************************/
/*   display multi strings                    */
/***************************************************/
/* r0  contains number strings address */
/* r1 address string1 */
/* r2 address string2 */
/* r3 address string3 */
/* other address on the stack */
/* thinck to add  number other address * 4 to add to the stack */
displayStrings:            @ INFO:  displayStrings
    push {r1-r4,fp,lr}     @ save des registres
    add fp,sp,#24          @ save paraméters address (6 registers saved * 4 bytes)
    mov r4,r0              @ save strings number
    cmp r4,#0              @ 0 string -> end
    ble 100f
    mov r0,r1              @ string 1
    bl affichageMess
    cmp r4,#1              @ number > 1
    ble 100f
    mov r0,r2
    bl affichageMess
    cmp r4,#2
    ble 100f
    mov r0,r3
    bl affichageMess
    cmp r4,#3
    ble 100f
    mov r3,#3
    sub r2,r4,#4
1:                         @ loop extract address string on stack
    ldr r0,[fp,r2,lsl #2]
    bl affichageMess
    subs r2,#1
    bge 1b
100:
    pop {r1-r4,fp,pc}
/******************************************************************/
/*     Conversion Float                                            */ 
/******************************************************************/
/* s0  contains Float */
/* r0 contains address conversion area  mini 20 charactèrs*/
/* r0 return result length */
/* see https://blog.benoitblanchon.fr/lightweight-float-to-string/ */
convertirFloat:
    push {r1-r7,lr}
    vpush {s0-s2}
    mov r6,r0                 @ save area address
    vmov r0,s0
    mov r1,#0
    vmov s1,r1
    movs r7,#0                @ result length
    movs r3,#'+'
    strb r3,[r6]              @ sign + forcing
    mov r2,r0
    lsls r2,#1                @ extraction bit 31
    bcc 1f                    @ positive ?
    lsrs r0,r2,#1             @ raz sign if negative
    movs r3,#'-'              @ sign -
    strb r3,[r6]
1:
    adds r7,#1                @ next position
    cmp r0,#0                 @ case of positive or negative 0
    bne 2f
    movs r3,#'0'
    strb r3,[r6,r7]           @ store character 0
    adds r7,#1                @ next position
    movs r3,#0
    strb r3,[r6,r7]           @ store  0 final
    mov r0,r7                 @ return length
    b 100f                    @ and end
2: 
    ldr r2,iMaskExposant
    mov r1,r0
    ands r1,r2                @ exposant = 255 ?
    cmp r1,r2
    bne 4f
    lsls r0,#10               @ bit 22 à 0 ?
    bcc 3f                    @ yes
    movs r2,#'N'              @ case of Nan. store byte, if not possible store int 
    strb r2,[r6]              @ area no aligned
    movs r2,#'a'
    strb r2,[r6,#1] 
    movs r2,#'n'
    strb r2,[r6,#2] 
    movs r2,#0                @ 0 final
    strb r2,[r6,#3] 
    movs r0,#3                @ return length 3
    b 100f
3:                            @ case infini positive or négative
    movs r2,#'I'
    strb r2,[r6,r7] 
    adds r7,#1
    movs r2,#'n'
    strb r2,[r6,r7] 
    adds r7,#1
    movs r2,#'f'
    strb r2,[r6,r7] 
    adds r7,#1
    movs r2,#0
    strb r2,[r6,r7]
    mov r0,r7
    b 100f
4:
    bl normaliserFloat
    mov r5,r0                @ save exposant
    VCVT.U32.f32  s2,s0      @ integer value of  integer part
    vmov r0,s2               @ integer part
    VCVT.F32.U32  s1,s2      @ conversion float
    vsub.f32 s1,s0,s1        @ extraction fract part
    vldr s2,iConst1
    vmul.f32 s1,s2,s1        @ to crop it in full

    VCVT.U32.f32  s1,s1      @ integer conversion
    vmov r4,s1               @ fract value
                             @ integer conversion in  r0
    mov r2,r6                @ save address area begin 
    adds r6,r7
    mov r1,r6
    bl conversion10
    add r6,r0
    movs r3,#','
    strb r3,[r6]
    adds r6,#1
 
    mov r0,r4                @ conversion fractional part
    mov r1,r6
    bl conversion10SP        @ spécial routine with conservation begin 0 
    add r6,r0
    subs r6,#1
                             @ remove trailing zeros
5:
    ldrb r0,[r6]
    cmp r0,#'0'
    bne 6f
    subs r6,#1
    b 5b
6:
    cmp r0,#','
    bne 7f
    subs r6,#1
7:
    adds r6,#1
    movs r3,#'E'
    strb r3,[r6]
    adds r6,#1
    mov r0,r5                  @ conversion exposant
    mov r3,r0
    lsls r3,#1
    bcc 4f
    rsbs r0,r0,#0
    movs r3,#'-'
    strb r3,[r6]
    adds r6,#1
4:
    mov r1,r6
    bl conversion10
    add r6,r0
    
    movs r3,#0
    strb r3,[r6]
    adds r6,#1
    mov r0,r6
    subs r0,r2                 @ return length result
    subs r0,#1                 @ - 0 final

100:
    vpop {s0-s2}
    pop {r1-r7,pc}
iMaskExposant:            .int 0xFF<<23
iConst1:                  .float 0f1E9

/***************************************************/
/*   normaliser float                              */
/***************************************************/
/* r0 contain float value (always positive value and <> Nan) */
/* s0 return new value  */
/* r0 return exposant */
normaliserFloat:
    push {lr}               @ save  registre
    vmov s0,r0              @ value float
    movs r0,#0              @ exposant
    vldr s1,iConstE7        @ no normalisation for value < 1E7
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 10f                 @ if s0  < iConstE7
    
    vldr s1,iConstE32
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 1f
    vldr s1,iConstE32
    vdiv.f32 s0,s0,s1
    adds r0,#32
1:
    vldr s1,iConstE16
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 2f
    vldr s1,iConstE16
    vdiv.f32 s0,s0,s1
    adds r0,#16
2:
    vldr s1,iConstE8
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 3f
    vldr s1,iConstE8
    vdiv.f32 s0,s0,s1
    adds r0,#8
3:
    vldr s1,iConstE4
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 4f
    vldr s1,iConstE4
    vdiv.f32 s0,s0,s1
    adds r0,#4
4:
    vldr s1,iConstE2
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 5f
    vldr s1,iConstE2
    vdiv.f32 s0,s0,s1
    adds r0,#2
5:
    vldr s1,iConstE1
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    blo 10f
    vldr s1,iConstE1
    vdiv.f32 s0,s0,s1
    adds r0,#1

10:
    vldr s1,iConstME5        @ pas de normalisation pour les valeurs > 1E-5
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 100f
    vldr s1,iConstME31
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 11f
    vldr s1,iConstE32

    vmul.f32 s0,s0,s1
    subs r0,#32
11:
    vldr s1,iConstME15
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 12f
    vldr s1,iConstE16
    vmul.f32 s0,s0,s1
    subs r0,#16
12:
    vldr s1,iConstME7
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 13f
    vldr s1,iConstE8
    vmul.f32 s0,s0,s1
    subs r0,#8
13:
    vldr s1,iConstME3
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 14f
    vldr s1,iConstE4
    vmul.f32 s0,s0,s1
    subs r0,#4
14:
    vldr s1,iConstME1
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 15f
    vldr s1,iConstE2
    vmul.f32 s0,s0,s1
    subs r0,#2
15:
    vldr s1,iConstE0
    vcmp.f32 s0,s1
    vmrs APSR_nzcv,FPSCR
    bhi 100f
    vldr s1,iConstE1
    vmul.f32 s0,s0,s1
    subs r0,#1

100:                       @ fin standard de la fonction
    pop {pc}               @ restaur des registres
.align 2
iConstE7:             .float 0f1E7
iConstE32:            .float 0f1E32
iConstE16:            .float 0f1E16
iConstE8:             .float 0f1E8
iConstE4:             .float 0f1E4
iConstE2:             .float 0f1E2
iConstE1:             .float 0f1E1
iConstME5:            .float 0f1E-5
iConstME31:           .float 0f1E-31
iConstME15:           .float 0f1E-15
iConstME7:            .float 0f1E-7
iConstME3:            .float 0f1E-3
iConstME1:            .float 0f1E-1
iConstE0:             .float 0f1E0    
/******************************************************************/
/*     Décimal Conversion                                         */ 
/******************************************************************/
/* r0 contain value et r1 address conversion area   */
conversion10SP:
    push {r1-r6,lr}            @ save  registers
    mov r5,r1
    mov r4,#8
    mov r2,r0
    mov r1,#10                 @ conversion decimale
1:                             @ begin loop
    mov r0,r2                  @ copy number or quotients
    bl division                @ r0 dividende r1 divisor r2 quotient r3 remainder
    add r3,#48                 @ compute digit  
    strb r3,[r5,r4]            @ store byte area address (r5) + offset (r4)
    subs r4,r4,#1              @ position précedente
    bge 1b                     @ and loop if not < zero
    mov r0,#8
    mov r3,#0
    strb r3,[r5,r0]            @ store 0 final
100:    
    pop {r1-r6,pc}             @ restaur registers   
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
/* for this file see task include a file in language ARM assembly */
.include "../affichage.inc"
Output:
Result  : +4,40000009E0
Result  : +4,25E0

Arturo

arr:  [1 2 3 4 5 6 7]
arr2: [1 2 3 4 5 6]
 
print median arr
print median arr2
Output:
4
3.5

AutoHotkey

Takes the lower of the middle two if length is even

seq = 4.1, 7.2, 1.7, 9.3, 4.4, 3.2, 5
MsgBox % median(seq, "`,")  ; 4.1

median(seq, delimiter)
{
  Sort, seq, ND%delimiter%
  StringSplit, seq, seq, % delimiter
  median := Floor(seq0 / 2)
  Return seq%median%
}

AWK

AWK arrays can be passed as parameters, but not returned, so they are usually global.

#!/usr/bin/awk -f

BEGIN {
    d[1] = 3.0
    d[2] = 4.0
    d[3] = 1.0
    d[4] = -8.4
    d[5] = 7.2
    d[6] = 4.0
    d[7] = 1.0
    d[8] = 1.2
    showD("Before: ")
    gnomeSortD()
    showD("Sorted: ")
    printf "Median: %f\n", medianD()
    exit
}

function medianD(     len, mid) {
    len = length(d)
    mid = int(len/2) + 1
    if (len % 2) return d[mid]
    else return (d[mid] + d[mid-1]) / 2.0
}

function gnomeSortD(    i) {
    for (i = 2; i <= length(d); i++) {
        if (d[i] < d[i-1]) gnomeSortBackD(i)
    }
}

function gnomeSortBackD(i,     t) {
    for (; i > 1 && d[i] < d[i-1]; i--) {
        t = d[i]
        d[i] = d[i-1]
        d[i-1] = t
    }
}

function showD(p,   i) {
    printf p
    for (i = 1; i <= length(d); i++) {
        printf d[i] " "
    }
    print ""
}

Example output:

Before: 3 4 1 -8.4 7.2 4 1 1.2 
Sorted: -8.4 1 1 1.2 3 4 4 7.2 
Median: 2.100000

BaCon

DECLARE a[] = { 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2 } TYPE FLOATING
DECLARE b[] = { 4.1, 7.2, 1.7, 9.3, 4.4, 3.2 } TYPE FLOATING

DEF FN Dim(x) = SIZEOF(x) / SIZEOF(double)

DEF FN Median(x) = IIF(ODD(Dim(x)), x[(Dim(x)-1)/2], (x[Dim(x)/2-1]+x[Dim(x)/2])/2 )

SORT a
PRINT "Median of a: ", Median(a)

SORT b
PRINT "Median of b: ", Median(b)
Output:
Median of a: 4.4
Median of b: 4.25

BASIC

Works with: FreeBASIC
Works with: PowerBASIC
Works with: QB64
Works with: QBasic
Works with: Visual Basic

This uses the Quicksort function described at Quicksort#BASIC, with arr()'s type changed to SINGLE.

Note that in order to truly work with the Windows versions of PowerBASIC, the module-level code must be contained inside FUNCTION PBMAIN. Similarly, in order to work under Visual Basic, the same module-level code must be contained with Sub Main.

DECLARE FUNCTION median! (vector() AS SINGLE)

DIM vec1(10) AS SINGLE, vec2(11) AS SINGLE, n AS INTEGER

RANDOMIZE TIMER

FOR n = 0 TO 10
    vec1(n) = RND * 100
    vec2(n) = RND * 100
NEXT
vec2(11) = RND * 100

PRINT median(vec1())
PRINT median(vec2())

FUNCTION median! (vector() AS SINGLE)
    DIM lb AS INTEGER, ub AS INTEGER, L0 AS INTEGER
    lb = LBOUND(vector)
    ub = UBOUND(vector)
    REDIM v(lb TO ub) AS SINGLE
    FOR L0 = lb TO ub
        v(L0) = vector(L0)
    NEXT
    quicksort v(), lb, ub
    IF ((ub - lb + 1) MOD 2) THEN
        median = v((ub + lb) / 2)
    ELSE
        median = (v(INT((ub + lb) / 2)) + v(INT((ub + lb) / 2) + 1)) / 2
    END IF
END FUNCTION

See also: BBC BASIC, Liberty BASIC, PureBasic, TI-83 BASIC, TI-89 BASIC.

BBC BASIC

      INSTALL @lib$+"SORTLIB"
      Sort% = FN_sortinit(0,0)

      DIM a(6), b(5)
      a() = 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2
      b() = 4.1, 7.2, 1.7, 9.3, 4.4, 3.2

      PRINT "Median of a() is " ; FNmedian(a())
      PRINT "Median of b() is " ; FNmedian(b())
      END

      DEF FNmedian(a())
      LOCAL C%
      C% = DIM(a(),1) + 1
      CALL Sort%, a(0)
      = (a(C% DIV 2) + a((C%-1) DIV 2)) / 2

Output:

Median of a() is 4.4
Median of b() is 4.25

BQN

A tacit definition from BQNcrate which sorts and takes the middle elements of the array.

Median ← (+´÷≠)∧⊏˜2⌊∘÷˜¯1‿0+≠

Median 5.961475‿2.025856‿7.262835‿1.814272‿2.281911‿4.854716
3.5683135

Bracmat

Each number is packaged in a little structure and these structures are accumulated in a sum. Bracmat keeps sums sorted, so the median is the term in the middle of the list, or the average of the two terms in the middle of the list. Notice that the input is converted to Bracmat's internal number representation, rational numbers, before being sorted. The output is converted back to 'double' variables. That last conversion is lossy.

( ( median
  =     begin decimals end int list
      , med med1 med2 num number
    .   ( convertToRational
        =
          .     new$(UFP,'(.$arg:?V))
              : ?ufp
            & (ufp..go)$
            & (ufp..export)$(Q.V)
        )
      & 0:?list
      &   whl
        ' ( !arg:%?number ?arg
          & convertToRational$!number:?rationalnumber
          & (!rationalnumber.)+!list:?list
          )
      & !list:?+[?end
      & (   !end*1/2:~/
          &   !list
            :   ?
              + [!(=1/2*!end+-1)
              + (?med1.?)
              + (?med2.?)
              + ?
          & !med1*1/2+!med2*1/2:?med
        | !list:?+[(div$(1/2*!end,1))+(?med.)+?
        )
      & (new$(UFP,'(.$med)).go)$
  )
& out$(median$("4.1" 4 "1.2" "6.235" "7868.33"))
&   out
  $ ( median
    $ ( "4.4"
        "2.3"
        "-1.7"
        "7.5"
        "6.6"
        "0.0"
        "1.9"
        "8.2"
        "9.3"
        "4.5"
      )
    )
& out$(median$(1 5 3 2 4))
& out$(median$(1 5 3 6 4 2))
);

Output:

4.0999999999999996E+00
4.4500000000000002E+00
3.0000000000000000E+00
3.5000000000000000E+00

C

#include <stdio.h>
#include <stdlib.h>

typedef struct floatList {
    float *list;
    int   size;
} *FloatList;

int floatcmp( const void *a, const void *b) {
    if (*(const float *)a < *(const float *)b) return -1;
    else return *(const float *)a > *(const float *)b;
}

float median( FloatList fl )
{
    qsort( fl->list, fl->size, sizeof(float), floatcmp);
    return 0.5 * ( fl->list[fl->size/2] + fl->list[(fl->size-1)/2]);
}

int main()
{
    static float floats1[] = { 5.1, 2.6, 6.2, 8.8, 4.6, 4.1 };
    static struct floatList flist1 = { floats1, sizeof(floats1)/sizeof(float) };

    static float floats2[] = { 5.1, 2.6, 8.8, 4.6, 4.1 };
    static struct floatList flist2 = { floats2, sizeof(floats2)/sizeof(float) };

    printf("flist1 median is %7.2f\n", median(&flist1)); /* 4.85 */
    printf("flist2 median is %7.2f\n", median(&flist2)); /* 4.60 */
    return 0;
}

Quickselect algorithm

Average O(n) time:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define MAX_ELEMENTS 1000000
 
/* Return the k-th smallest item in array x of length len */
double quick_select(int k, double *x, int len)
{
   inline void swap(int a, int b)
   {
      double t = x[a];
      x[a] = x[b], x[b] = t;
   }
 
   int left = 0, right = len - 1;
   int pos, i;
   double pivot;
 
   while (left < right)
   {
      pivot = x[k];
      swap(k, right);
      for (i = pos = left; i < right; i++)
      {
         if (x[i] < pivot)
         {
            swap(i, pos);
            pos++;
         }
      }
      swap(right, pos);
      if (pos == k) break;
      if (pos < k) left = pos + 1;
      else right = pos - 1;
   }
   return x[k];
}
 
int main(void)
{
   int i, length;
   double *x, median;
 
   /* Initialize random length double array with random doubles */
   srandom(time(0));
   length = random() % MAX_ELEMENTS;
   x = malloc(sizeof(double) * length);
   for (i = 0; i < length; i++)
   {
      // shifted by RAND_MAX for negative values
      // divide by a random number for floating point
      x[i] = (double)(random() - RAND_MAX / 2) / (random() + 1); // + 1 to not divide by 0
   }
 

   if (length % 2 == 0) // Even number of elements, median is average of middle two
   {
      median = (quick_select(length / 2, x, length) + quick_select(length / 2 - 1, x, length / 2)) / 2;
   } 
   else // select middle element
   {
      median = quick_select(length / 2, x, length);
   }
 

   /* Sanity testing of median */
   int less = 0, more = 0, eq = 0;
   for (i = 0; i < length; i++)
   {
      if (x[i] < median) less ++;
      else if (x[i] > median) more ++;
      else eq ++;
   }
   printf("length: %d\nmedian: %lf\n<: %d\n>: %d\n=: %d\n", length, median, less, more, eq);

   free(x);
   return 0;
}

Output:

length: 992021
median: 0.000473
<: 496010
>: 496010
=: 1

C#

Works with: C# version 10+
double median(double[] arr)
{
	var sorted = arr.OrderBy(x => x).ToList();
	var mid = arr.Length / 2;
	return arr.Length % 2 == 0
		? (sorted[mid] + sorted[mid-1]) / 2
		: sorted[mid];
}

var write = (double[] x) =>
	Console.WriteLine($"[{string.Join(", ", x)}]: {median(x)}");
write(new double[] { 1, 5, 3, 6, 4, 2 }); //even
write(new double[] { 1, 5, 3, 6, 4, 2, 7 }); //odd
write(new double[] { 5 }); //single
Output:
[1, 5, 3, 6, 4, 2]: 3.5
[1, 5, 3, 6, 4, 2, 7]: 4
[5]: 5

C++

This function runs in linear time on average.

#include <algorithm>

// inputs must be random-access iterators of doubles
// Note: this function modifies the input range
template <typename Iterator>
double median(Iterator begin, Iterator end) {
  // this is middle for odd-length, and "upper-middle" for even length
  Iterator middle = begin + (end - begin) / 2;

  // This function runs in O(n) on average, according to the standard
  std::nth_element(begin, middle, end);

  if ((end - begin) % 2 != 0) { // odd length
    return *middle;
  } else { // even length
    // the "lower middle" is the max of the lower half
    Iterator lower_middle = std::max_element(begin, middle);
    return (*middle + *lower_middle) / 2.0;
  }
}

#include <iostream>

int main() {
  double a[] = {4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2};
  double b[] = {4.1, 7.2, 1.7, 9.3, 4.4, 3.2};

  std::cout << median(a+0, a + sizeof(a)/sizeof(a[0])) << std::endl; // 4.4
  std::cout << median(b+0, b + sizeof(b)/sizeof(b[0])) << std::endl; // 4.25

  return 0;
}

Order Statistic Tree

Uses a GNU C++ policy-based data structure to compute median in O(log n) time.

Library: gnu_pbds
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

// the std::less_equal<> comparator allows the tree to support duplicates
typedef __gnu_pbds::tree<double, __gnu_pbds::null_type, std::less_equal<double>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> ost_t;

// The lookup method, find_by_order (aka Select), is O(log n) for this data structure, much faster than std::nth_element()
double median(ost_t &OST)
{
    int n = OST.size();
    int m = n/2;
    if (n == 1)
        return *OST.find_by_order(0);
    if (n == 2)
        return (*OST.find_by_order(0) + *OST.find_by_order(1)) / 2;
    
    if (n & 1) // odd number of elements
        return *OST.find_by_order(m);
    else // even number of elements
        return (*OST.find_by_order(m) + *OST.find_by_order(m-1)) / 2;
}

int main(int argc, char* argv[])
{
    ost_t ostree;
    
    // insertion is also O(log n) for OSTs
    ostree.insert(4.1);
    ostree.insert(7.2);
    ostree.insert(1.7);
    ostree.insert(9.3);
    ostree.insert(4.4);
    ostree.insert(3.2);

    printf("%.3f\n", median(ostree)); // 4.250

    return 0;
}

Clojure

Simple:

(defn median [ns]
  (let [ns (sort ns)
        cnt (count ns)
        mid (bit-shift-right cnt 1)]
    (if (odd? cnt)
      (nth ns mid)
      (/ (+ (nth ns mid) (nth ns (dec mid))) 2))))

COBOL

Intrinsic function:

FUNCTION MEDIAN(some-table (ALL))

Common Lisp

The recursive partitioning solution, without the median of medians optimization.

((defun select-nth (n list predicate)
  "Select nth element in list, ordered by predicate, modifying list."
  (do ((pivot (pop list))
       (ln 0) (left '())
       (rn 0) (right '()))
      ((endp list)
       (cond
        ((< n ln) (select-nth n left predicate))
        ((eql n ln) pivot)
        ((< n (+ ln rn 1)) (select-nth (- n ln 1) right predicate))
        (t (error "n out of range."))))
    (if (funcall predicate (first list) pivot)
      (psetf list (cdr list)
             (cdr list) left
             left list
             ln (1+ ln))
      (psetf list (cdr list)
             (cdr list) right
             right list
             rn (1+ rn)))))

(defun median (list predicate)
  (select-nth (floor (length list) 2) list predicate))

Craft Basic

define limit = 10, iterations = 6
define iteration, size, middle, plusone
define point, top, high, low, pivot

dim list[limit]
dim stack[limit]

for iteration = 1 to iterations

	gosub fill
	gosub median

next iteration

end

sub fill

	print "list: ",

	erasearray list

	let size = int(rnd * limit) + 1

	if size <= 2 then

		let size = 3

	endif

	for i = 0 to size - 1

		let list[i] = rnd * 1000 + rnd
		print list[i],

		gosub printcomma

	next i

return

sub median

	gosub sort

	print newline, "size: ", size, tab,

	let middle = int((size - 1)/ 2)
	print "middle: ", middle + 1, tab,

	if size mod 2 then

		print "median: ", list[middle]

	else

		let plusone = middle + 1
		print "median: ", (list[middle] + list[plusone]) / 2

	endif

	print

return

sub sort

	let low = 0
	let high = size - 1
	let top = -1

	let top = top + 1
	let stack[top] = low
	let top = top + 1
	let stack[top] = high
 
	do

		if top < 0 then

			break

		endif

		let high = stack[top]
		let top = top - 1
		let low = stack[top]
		let top = top - 1

		let i = low - 1
		
		for j = low to high - 1

			if list[j] <= list[high] then

				let i = i + 1
				let t = list[i]
				let list[i] = list[j]
				let list[j] = t

			endif

		next j

		let point = i + 1
		let t = list[point]
		let list[point] = list[high]
		let list[high] = t
		let pivot = i + 1

		if pivot - 1 > low then

			let top = top + 1
			let stack[top] = low
			let top = top + 1
			let stack[top] = pivot - 1

		endif
  
		if pivot + 1 < high then

			let top = top + 1
			let stack[top] = pivot + 1
			let top = top + 1
			let stack[top] = high

		endif

		wait

	loop top >= 0

	print newline, "sorted: ",

	for i = 0 to size - 1

		print list[i],
		gosub printcomma

	next i

return

sub printcomma

	if i < size - 1 then

		print comma, " ",

	endif

return
Output:
list: 290.66, 870.46, 880.86
sorted: 290.66, 870.46, 880.86
size: 3	middle: 2	median: 870.46

list: 910.91, 50.79, 790.58, 960.61
sorted: 50.79, 790.58, 910.91, 960.61
size: 4	middle: 2	median: 850.74

list: 570.31, 500.16, 490.97, 370.48, 240.18, 880.23, 190.61, 950.19
sorted: 190.61, 240.18, 370.48, 490.97, 500.16, 570.31, 880.23, 950.19
size: 8	middle: 4	median: 495.57

list: 120.87, 570.87, 570.85, 800.27, 200.04, 250.09, 870.04, 200.58, 800.61
sorted: 120.87, 200.04, 200.58, 250.09, 570.85, 570.87, 800.27, 800.61, 870.04
size: 9	middle: 5	median: 570.85

list: 810.33, 760.55, 420.22, 730.64, 350.96
sorted: 350.96, 420.22, 730.64, 760.55, 810.33
size: 5	middle: 3	median: 730.64

list: 40.12, 860.77, 960.29, 920.13
sorted: 40.12, 860.77, 920.13, 960.29
size: 4	middle: 2	median: 890.45

Crystal

def median(ary)
  srtd = ary.sort
  alen = srtd.size
  0.5*(srtd[(alen-1)//2] + srtd[alen//2])
end

a = [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]
puts median a

a = [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2, 5.0]
puts median a

a = [5.0]
puts median a
Output:
4.4
4.7
5.0

D

import std.stdio, std.algorithm;

T median(T)(T[] nums) pure nothrow {
    nums.sort();
    if (nums.length & 1)
        return nums[$ / 2];
    else
        return (nums[$ / 2 - 1] + nums[$ / 2]) / 2.0;
}

void main() {
    auto a1 = [5.1, 2.6, 6.2, 8.8, 4.6, 4.1];
    writeln("Even median: ", a1.median);

    auto a2 = [5.1, 2.6, 8.8, 4.6, 4.1];
    writeln("Odd median:  ", a2.median);
}
Output:
Even median: 4.85
Odd median:  4.6

Delphi

program AveragesMedian;

{$APPTYPE CONSOLE}

uses Generics.Collections, Types;

function Median(aArray: TDoubleDynArray): Double;
var
  lMiddleIndex: Integer;
begin
  TArray.Sort<Double>(aArray);

  lMiddleIndex := Length(aArray) div 2;
  if Odd(Length(aArray)) then
    Result := aArray[lMiddleIndex]
  else
    Result := (aArray[lMiddleIndex - 1] + aArray[lMiddleIndex]) / 2;
end;

begin
  Writeln(Median(TDoubleDynArray.Create(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2)));
  Writeln(Median(TDoubleDynArray.Create(4.1, 7.2, 1.7, 9.3, 4.4, 3.2)));
end.

DuckDB

Works with: DuckDB version V1.0

DuckDB provides both the median() function for ascertaining the median values of a column, and the list_median() function for determining the median of a list of any type. For non-numeric data, these functions are not Procrustean, as illustrated by the last example below. Notice also that the computed median of a list of integers is a DOUBLE even when the median value is actually an integer.

Here's a typescript, wherein "D " is the DuckDB prompt.

D select median(x) from (select unnest( [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]) as x );
┌──────────────┐
│  median(x)   │
│ decimal(2,1) │
├──────────────┤
│          4.4 │
└──────────────┘

D select list_median([4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]) as median;
┌──────────────┐
│    median    │
│ decimal(2,1) │
├──────────────┤
│          4.4 │
└──────────────┘

D select list_median([1,2,3]::INTEGER[3]) as median;
┌────────┐
│ median │
│ double │
├────────┤
│    2.0 │
└────────┘

D select list_median(['d', 'a','b', 'c']) as median;
┌─────────┐
│ median  │
│ varchar │
├─────────┤
│ b       │
└─────────┘


E

TODO: Use the selection algorithm, whatever that is

def median(list) {
    def sorted := list.sort()
    def count := sorted.size()
    def mid1 := count // 2
    def mid2 := (count - 1) // 2
    if (mid1 == mid2) {          # avoid inexact division
        return sorted[mid1]
    } else {
        return (sorted[mid1] + sorted[mid2]) / 2
    }
}
? median([1,9,2])
# value: 2

? median([1,9,2,4])
# value: 3.0

EasyLang

proc quickselect k . list[] res .
   # 
   subr partition
      mid = left
      for i = left + 1 to right
         if list[i] < list[left]
            mid += 1
            swap list[i] list[mid]
         .
      .
      swap list[left] list[mid]
   .
   left = 1
   right = len list[]
   while left < right
      partition
      if mid < k
         left = mid + 1
      elif mid > k
         right = mid - 1
      else
         left = right
      .
   .
   res = list[k]
.
proc median . list[] res .
   h = len list[] div 2 + 1
   quickselect h list[] res
   if len list[] mod 2 = 0
      quickselect h - 1 list[] h
      res = (res + h) / 2
   .
.
test[] = [ 4.1 5.6 7.2 1.7 9.3 4.4 3.2 ]
median test[] med
print med
test[] = [ 4.1 7.2 1.7 9.3 4.4 3.2 ]
median test[] med
print med
4.40
4.25

EchoLisp

(define (median L) ;; O(n log(n))
	(set! L (vector-sort! < (list->vector L)))
	(define dim (// (vector-length L) 2))
	(if (integer? dim)
		(// (+ [L dim] [L (1- dim)]) 2)
		[L (floor dim)]))

(median '( 3 4 5))
    4
(median '(6 5 4 3))
    4.5
(median (iota 10000))
    4999.5
(median (iota 10001))
    5000

Elena

ELENA 6.x :

import system'routines;
import system'math;
import extensions;
 
extension op 
{
    get Median()
    {
        var sorted := self.ascendant();

        var len := sorted.Length;
        if (len == 0)
        { 
            ^ nil 
        }
        else
        {
            var middleIndex := len / 2;
            if (len.mod(2) == 0)
            { 
                ^ (sorted[middleIndex - 1] + sorted[middleIndex]) / 2 
            }
            else
            { 
                ^ sorted[middleIndex] 
            }
        }
    }
}    

public program()
{
    var a1 := new real[]{4.1r, 5.6r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r};
    var a2 := new real[]{4.1r, 7.2r, 1.7r, 9.3r, 4.4r, 3.2r};
    
    console.printLine("median of (",a1.asEnumerable(),") is ",a1.Median);
    console.printLine("median of (",a2.asEnumerable(),") is ",a2.Median);
    
    console.readChar()
}
Output:
median of (4.1,5.6,7.2,1.7,9.3,4.4,3.2) is 4.4
median of (4.1,7.2,1.7,9.3,4.4,3.2) is 4.25

Elixir

Translation of: Erlang
defmodule Average do
  def median([]), do: nil
  def median(list) do
    len = length(list)
    sorted = Enum.sort(list)
    mid = div(len, 2)
    if rem(len,2) == 0, do: (Enum.at(sorted, mid-1) + Enum.at(sorted, mid)) / 2,
                      else: Enum.at(sorted, mid)
  end 
end
 
median = fn list -> IO.puts "#{inspect list} => #{inspect Average.median(list)}" end
median.([])
Enum.each(1..6, fn i ->
  (for _ <- 1..i, do: :rand.uniform(6)) |> median.()
end)
Output:
[] => nil
[4] => 4
[1, 6] => 3.5
[5, 2, 4] => 4
[2, 3, 5, 1] => 2.5
[3, 2, 6, 3, 2] => 3
[6, 4, 2, 3, 1, 3] => 3.0

EMal

Sort

fun median ← real by some real values
  values ← values.sort()
  int mid ← values.length / 2
  return when(values.length % 2 æ 0, (values[mid] + values[mid - 1]) / 2.0, values[mid])
end
writeLine(median(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2, 5.0))
writeLine(median(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2))
Output:
4.7
4.4

Quickselect

fun median ← real by some real values
  fun swap ← void by int a, int b
    real t ← values[a]
    values[a] ← values[b]
    values[b] ← t
  end
  fun select ← real by int k
    int left ← 0
    int right ← values.length - 1
    while left < right
      real pivot ← values[k]
      swap(k, right)
      int pos ← left
      for int i ← left; i < right; ++i
        if values[i] < pivot
	      swap(i, pos)
	      ++pos
        end
      end
	  swap(right, pos)
      if pos æ k do break
      else if pos < k do left ← pos + 1
      else do right ← pos - 1 end
    end
    return values[k]
  end
  int halfLength ← values.length / 2
  return when(values.length % 2 æ 0,
    (select(halfLength) + select(halfLength - 1)) / 2.0, 
	select(halfLength))
end
writeLine(median(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2, 5.0))
writeLine(median(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2))
Output:
4.7
4.4

Erlang

-module(median).
-import(lists, [nth/2, sort/1]).
-compile(export_all).


test(MaxInt,ListSize,TimesToRun) ->
    test(MaxInt,ListSize,TimesToRun,[[],[]]).

test(_,_,0,[GMAcc, OMAcc]) ->
    Len = length(GMAcc),
    {GMT,GMV} = lists:foldl(fun({T, V}, {AT,AV}) -> {AT + T, AV + V} end, {0,0}, GMAcc),
    {OMT,OMV} = lists:foldl(fun({T, V}, {AT,AV}) -> {AT + T, AV + V} end, {0,0}, OMAcc),
    io:format("QuickSelect Time: ~p, Val: ~p~nOriginal Time: ~p, Val: ~p~n", [GMT/Len, GMV/Len, OMT/Len, OMV/Len]);
test(M,N,T,[GMAcc, OMAcc]) ->
    L = [rand:uniform(M) || _ <- lists:seq(1,N)],
    GM = timer:tc(fun() -> qs_median(L) end),
    OM = timer:tc(fun() -> median(L) end),
    test(M,N,T-1,[[GM|GMAcc], [OM|OMAcc]]).

median(Unsorted) ->
    Sorted = sort(Unsorted),
    Length = length(Sorted),
    Mid = Length div 2,
    Rem = Length rem 2,
    (nth(Mid+Rem, Sorted) + nth(Mid+1, Sorted)) / 2.

% ***********************************************************
% median based on quick select with optimizations for repeating numbers
% if it really matters it's a little faster
% by Roman Rabinovich
% ***********************************************************

qs_median([]) -> error;
qs_median([X]) -> X;
qs_median([P|_Tail] = List) ->
    TargetPos = length(List)/2 + 0.5,
    qs_median(List, TargetPos, P, 0).
 
qs_median([X], 1, _, 0) ->  X;
qs_median([X], 1, _, Acc) ->  (X + Acc)/2;
qs_median([P|Tail], TargetPos, LastP, Acc) ->
    Smaller = [X || X <- Tail, X < P],
    LS = length(Smaller),
    qs_continue(P, LS, TargetPos, LastP, Smaller, Tail, Acc).

qs_continue(P, LS, TargetPos, _, _, _, 0) when LS + 1 == TargetPos -> P;
qs_continue(P, LS, TargetPos, _, _, _, Acc) when LS + 1 == TargetPos -> (P + Acc)/2;
qs_continue(P, 0, TargetPos, LastP, _SM, _TL, _Acc) when TargetPos == 0.5 ->
    (P+LastP)/2;
qs_continue(P, LS, TargetPos, _LastP, SM, _TL, _Acc) when TargetPos == LS + 0.5 ->
    qs_median(SM, TargetPos - 0.5, P, P);
qs_continue(P, LS, TargetPos, _LastP, SM, _TL, Acc) when LS + 1 > TargetPos  ->
    qs_median(SM, TargetPos, P, Acc);
qs_continue(P, LS, TargetPos, _LastP, _SM, TL, Acc) ->
    Larger = [X || X <- TL, X >= P],
    NewPos= TargetPos - LS -1,
    case NewPos == 0.5 of 
        true -> 
            qs_median(Larger, 1, P, P);
        false -> 
            qs_median(Larger, NewPos, P, Acc)
    end.

ERRE

PROGRAM MEDIAN

DIM X[10]

PROCEDURE QUICK_SELECT
    LT=0 RT=L-1
    J=LT
    REPEAT
        PT=X[K]
        SWAP(X[K],X[RT])
        P=LT
        FOR I=P TO RT-1 DO
            IF X[I]<PT THEN SWAP(X[I],X[P]) P=P+1 END IF
        END FOR
        SWAP(X[RT],X[P])
        IF P=K THEN EXIT PROCEDURE END IF
        IF P<K THEN LT=P+1 END IF
        IF P>=K THEN RT=P-1 END IF
    UNTIL J>RT
END PROCEDURE

PROCEDURE MEDIAN
    K=INT(L/2)
    QUICK_SELECT
    R=X[K]
    IF L-2*INT(L/2)<>0 THEN R=(R+X[K+1])/2 END IF
END PROCEDURE

BEGIN
   PRINT(CHR$(12);) !CLS
   X[0]=4.4 X[1]=2.3 X[2]=-1.7 X[3]=7.5 X[4]=6.6 X[5]=0
   X[6]=1.9 X[7]=8.2 X[8]=9.3 X[9]=4.5 X[10]=-11.7
   L=11
   MEDIAN
   PRINT(R)
END PROGRAM

Ouput is 5.95

Euler Math Toolbox

The following function does much more than computing the median. It can handle a matrix of x values row by row. Then it can handle multiplicities in the vector v. Moreover it can search for the p median, not only the p=0.5 median.

>type median
 function median (x, v: none, p)
 
 ## Default for v : none
 ## Default for p : 0.5
 
     m=rows(x);
     if m>1 then
         y=zeros(m,1);
         loop 1 to m;
             y[#]=median(x[#],v,p);
         end;
         return y;
     else
         if v<>none then
             {xs,i}=sort(x); vsh=v[i];
             n=cols(xs);
             ns=sum(vsh);
             i=1+p*(ns-1); i0=floor(i);
             vs=cumsum(vsh);
             loop 1 to n
                 if vs[#]>i0 then 
                     return xs[#]; 
                 elseif vs[#]+1>i0 then
                     k=#+1; 
                     repeat; 
                         if vsh[k]>0 or k>n then break; endif; 
                         k=k+1;
                     end;
                     return (1-(i-i0))*xs[#]+(i-i0)*xs[k]+0; 
                 endif;
             end;
             return xs[n];
         else
             xs=sort(x); 
             n=cols(x);
             i=1+p*(n-1); i0=floor(i);
             if i0==n then return xs[n]; endif;
             return (i-i0)*xs[i+1]+(1-(i-i0))*xs[i];
         endif;
     endif;
 endfunction
>median(1:10)
 5.5
>median(1:9)
 5
>median(1:10,p=0.2)
 2.8
>0.2*10+0.8*1
 2.8

Euphoria

function median(sequence s)
    atom min,k
    -- Selection sort of half+1
    for i = 1 to length(s)/2+1 do
        min = s[i]
        k = 0
        for j = i+1 to length(s) do
            if s[j] < min then
                min = s[j]
                k = j
            end if
        end for
        if k then
            s[k] = s[i]
            s[i] = min
        end if
    end for
    if remainder(length(s),2) = 0 then
        return (s[$/2]+s[$/2+1])/2
    else
        return s[$/2+1]
    end if
end function

? median({ 4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5 })

Output:

4.45

Excel

Assuming the values are entered in the A column, type into any cell which will not be part of the list :

=MEDIAN(A1:A10)

Assuming 10 values will be entered, alternatively, you can just type

=MEDIAN(

and then select the start and end cells, not necessarily in the same row or column.

The output for the first expression, for any 10 numbers is

23	11,5
21	
12	
3	
19	
7	
23	
11	
9	
0

F#

Median of Medians algorithm implementation

let rec splitToFives list = 
    match list with
        | a::b::c::d::e::tail ->
            ([a;b;c;d;e])::(splitToFives tail)
        | [] -> []
        | _ -> 
                let left = 5 - List.length (list)
                let last = List.append list (List.init left (fun _ -> System.Double.PositiveInfinity) )
                in [last]

let medianFromFives =
    List.map ( fun (i:float list) ->
        List.nth (List.sort i) 2 ) 

let start l = 
    let rec magicFives list k =
        if List.length(list) <= 10 then
            List.nth (List.sort list) (k-1)
        else
            let s = splitToFives list
            let M = medianFromFives s
            let m = magicFives M (int(System.Math.Ceiling((float(List.length M))/2.)))
            let (ll,lg) = List.partition ( fun i -> i < m ) list
            let (le,lg) = List.partition ( fun i -> i = m ) lg
            in
               if (List.length ll >= k) then 
                    magicFives ll k
               else if (List.length ll + List.length le >= k ) then m
               else
                    magicFives lg (k-(List.length ll)-(List.length le))
    in
        let len = List.length l in
        if (len % 2 = 1) then
            magicFives l ((len+1)/2)
        else
            let a = magicFives l (len/2)
            let b = magicFives l ((len/2)+1)
            in (a+b)/2.


let z = [1.;5.;2.;8.;7.;2.]
start z
let z' = [1.;5.;2.;8.;7.]
start z'

Factor

The quicksort-style solution, with random pivoting. Takes the lesser of the two medians for even sequences.

USING: arrays kernel locals math math.functions random sequences ;
IN: median

: pivot ( seq -- pivot ) random ;

: split ( seq pivot -- {lt,eq,gt} )
  [ [ < ] curry partition ] keep
  [ = ] curry partition
  3array ;

DEFER: nth-in-order
:: nth-in-order-recur ( seq ind -- elt )
  seq dup pivot split
  dup [ length ] map  0 [ + ] accumulate nip
  dup [ ind <= [ 1 ] [ 0 ] if ] map sum 1 -
  [ swap nth ] curry bi@
  ind swap -
  nth-in-order ;

: nth-in-order ( seq ind -- elt )
  dup 0 =
  [ drop first ]
  [ nth-in-order-recur ]
  if ;

: median ( seq -- median )
  dup length 1 - 2 / floor nth-in-order ;

Usage:

( scratchpad ) 11 iota median .
5
( scratchpad ) 10 iota median .
4

Forth

This uses the O(n) algorithm derived from quicksort.

-1 cells constant -cell
: cell-   -cell + ;

defer lessthan ( a@ b@ -- ? )   ' < is lessthan

: mid ( l r -- mid ) over - 2/ -cell and + ;

: exch ( addr1 addr2 -- ) dup @ >r over @ swap ! r> swap ! ;

: part ( l r -- l r r2 l2 )
  2dup mid @ >r ( r: pivot )
  2dup begin
    swap begin dup @  r@ lessthan while cell+ repeat
    swap begin r@ over @ lessthan while cell- repeat
    2dup <= if 2dup exch >r cell+ r> cell- then
  2dup > until  r> drop ;

0 value midpoint

: select ( l r -- )
  begin 2dup < while
    part
    dup  midpoint >= if nip nip ( l l2 ) else
    over midpoint <= if drop rot drop swap ( r2 r ) else
    2drop 2drop exit then then
  repeat 2drop ;
  
: median ( array len -- m )
  1- cells over +  2dup mid to midpoint
  select           midpoint @ ;
create test 4 , 2 , 1 , 3 , 5 ,

test 4 median .   \ 2
test 5 median .   \ 3

Fortran

Works with: Fortran version 90 and later
program Median_Test

  real            :: a(7) = (/ 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2 /), &
                     b(6) = (/ 4.1, 7.2, 1.7, 9.3, 4.4, 3.2 /)

  print *, median(a)
  print *, median(b)

contains

  function median(a, found)
    real, dimension(:), intent(in) :: a
      ! the optional found argument can be used to check
      ! if the function returned a valid value; we need this
      ! just if we suspect our "vector" can be "empty"
    logical, optional, intent(out) :: found
    real :: median

    integer :: l
    real, dimension(size(a,1)) :: ac

    if ( size(a,1) < 1 ) then
       if ( present(found) ) found = .false.
    else
       ac = a
       ! this is not an intrinsic: peek a sort algo from
       ! Category:Sorting, fixing it to work with real if
       ! it uses integer instead.
       call sort(ac)

       l = size(a,1)
       if ( mod(l, 2) == 0 ) then
          median = (ac(l/2+1) + ac(l/2))/2.0
       else
          median = ac(l/2+1)
       end if

       if ( present(found) ) found = .true.
    end if

  end function median

end program Median_Test

If one refers to Quickselect_algorithm#Fortran which offers function FINDELEMENT(K,A,N) that returns the value of A(K) when the array of N elements has been rearranged if necessary so that A(K) is the K'th in order, then, supposing that a version is devised using the appropriate type for array A,

      K = N/2
      MEDIAN = FINDELEMENT(K + 1,A,N)
      IF (MOD(N,2).EQ.0) MEDIAN = (FINDELEMENT(K,A,N) + MEDIAN)/2

As well as returning a result, the function possibly re-arranges the elements of the array, which is not "pure" behaviour. Not to the degree of fully sorting them, merely that all elements before K are not larger than A(K) as it now is, and all elements after K are not smaller than A(K).

FreeBASIC

' FB 1.05.0 Win64

Sub quicksort(a() As Double, first As Integer, last As Integer)
  Dim As Integer length = last - first + 1
  If length < 2 Then Return 
  Dim pivot As Double = a(first + length\ 2)
  Dim lft As Integer = first 
  Dim rgt As Integer = last 
  While lft <= rgt
    While a(lft) < pivot
      lft +=1
    Wend
    While a(rgt) > pivot
      rgt -= 1
    Wend
    If lft <= rgt Then
       Swap a(lft), a(rgt)
       lft += 1
       rgt -= 1
    End If 
  Wend
  quicksort(a(), first, rgt)
  quicksort(a(), lft, last)
End Sub

Function median(a() As Double) As Double
  Dim lb As Integer = LBound(a)
  Dim ub As Integer = UBound(a)
  Dim length As Integer = ub - lb + 1
  If length = 0 Then Return 0.0/0.0 '' NaN
  If length = 1 Then Return a(ub)
  Dim mb As Integer = (lb + ub) \2
  If length Mod 2 = 1 Then Return a(mb)
  Return (a(mb) + a(mb + 1))/2.0
End Function

Dim a(0 To 9) As Double = {4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5} 
quicksort(a(), 0, 9)
Print "Median for all 10 elements  : "; median(a())
' now get rid of final element
Dim b(0 To 8) As Double = {4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3} 
quicksort(b(), 0, 8)
Print "Median for first 9 elements : "; median(b())
Print
Print "Press any key to quit"
Sleep
Output:
Median for all 10 elements  :  4.45
Median for first 9 elements :  4.4

FutureBasic

FB has native averaging functions.

local fn MedianAverage( arguments as CFArrayRef ) as CFStringRef
  ExpressionRef expRef = fn ExpressionForFunction( @"median:", @[fn ExpressionForConstantValue( arguments )] )
  CFNumberRef   result = fn ExpressionValueWithObject( expRef, NULL, NULL )
  CFStringRef   median = fn NumberStringValue( result )
end fn = median

print fn MedianAverage( @[@1, @9, @2] )                                                       // 2
print fn MedianAverage( @[@1, @9, @2, @4] )                                                   // 3
print fn MedianAverage( @[@5.961475, @2.025856, @7.262835, @1.814272, @2.281911, @4.854716] ) // 3.5683135
print fn MedianAverage( @[@4.1, @5.6, @7.2, @1.7, @9.3, @4.4, @3.2] )                         // 4.4
print fn MedianAverage( @[@40.12, @860.77, @960.29, @920.13] )                                // 890.45

HandleEvents
Output:
2
3
3.5683135
4.4
890.45



GAP

Median := function(v) 
  local n, w;
  w := SortedList(v);
  n := Length(v);
  return (w[QuoInt(n + 1, 2)] + w[QuoInt(n, 2) + 1]) / 2;
end;

a := [41, 56, 72, 17, 93, 44, 32];
b := [41, 72, 17, 93, 44, 32];     

Median(a);
# 44
Median(b);
# 85/2

Go

Sort

Go built-in sort. O(n log n).

package main

import (
    "fmt"
    "sort"
)

func main() {
    fmt.Println(median([]float64{3, 1, 4, 1}))    // prints 2
    fmt.Println(median([]float64{3, 1, 4, 1, 5})) // prints 3
}

func median(a []float64) float64 {
    sort.Float64s(a)
    half := len(a) / 2
    m := a[half]
    if len(a)%2 == 0 {
        m = (m + a[half-1]) / 2
    }
    return m
}

Partial selection sort

The task description references the WP entry for "selection algorithm" which (as of this writing) gives just one pseudocode example, which is implemented here. As the WP article notes, it is O(kn). Unfortunately in the case of median, k is n/2 so the algorithm is O(n^2). Still, it gives the idea of median by selection. Note that the partial selection sort does leave the k smallest values sorted, so in the case of an even number of elements, the two elements to average are available after a single call to sel().

package main

import "fmt"

func main() {
    fmt.Println(median([]float64{3, 1, 4, 1}))    // prints 2
    fmt.Println(median([]float64{3, 1, 4, 1, 5})) // prints 3
}

func median(a []float64) float64 {
    half := len(a) / 2
    med := sel(a, half)
    if len(a)%2 == 0 {
        return (med + a[half-1]) / 2
    }
    return med
}

func sel(list []float64, k int) float64 {
    for i, minValue := range list[:k+1] {
        minIndex := i
        for j := i + 1; j < len(list); j++ {
            if list[j] < minValue {
                minIndex = j
                minValue = list[j]
                list[i], list[minIndex] = minValue, list[i]
            }
        }
    }
    return list[k]
}

Quickselect

It doesn't take too much more code to implement a quickselect with random pivoting, which should run in expected time O(n). The qsel function here permutes elements of its parameter "a" in place. It leaves the slice somewhat more ordered, but unlike the sort and partial sort examples above, does not guarantee that element k-1 is in place. For the case of an even number of elements then, median must make two separate qsel() calls.

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    fmt.Println(median([]float64{3, 1, 4, 1}))    // prints 2
    fmt.Println(median([]float64{3, 1, 4, 1, 5})) // prints 3
}

func median(list []float64) float64 {
    half := len(list) / 2
    med := qsel(list, half)
    if len(list)%2 == 0 {
        return (med + qsel(list, half-1)) / 2
    }
    return med
}

func qsel(a []float64, k int) float64 {
    for len(a) > 1 {
        px := rand.Intn(len(a))
        pv := a[px]
        last := len(a) - 1
        a[px], a[last] = a[last], pv
        px = 0
        for i, v := range a[:last] {
            if v < pv {
                a[px], a[i] = v, a[px]
                px++
            }
        }
        if px == k {
            return pv
        }
        if k < px {
            a = a[:px]
        } else {
            // swap elements.  simply assigning a[last] would be enough to
            // allow qsel to return the correct result but it would leave slice
            // "a" unusable for subsequent use.  we want this full swap so that
            // we can make two successive qsel calls in the case of median
            // of an even number of elements.
            a[px], a[last] = pv, a[px]
            a = a[px+1:]
            k -= px + 1
        }
    }
    return a[0]
}

Groovy

Solution (brute force sorting, with arithmetic averaging of dual midpoints (even sizes)):

def median(Iterable col) {
    def s = col as SortedSet
    if (s == null) return null
    if (s.empty) return 0
    def n = s.size()
    def m = n.intdiv(2)
    def l = s.collect { it }
    n%2 == 1 ? l[m] : (l[m] + l[m-1])/2 
}

Test:

def a = [4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5]
def sz = a.size()

(0..sz).each {
    println """${median(a[0..<(sz-it)])} == median(${a[0..<(sz-it)]})
${median(a[it..<sz])} == median(${a[it..<sz]})"""
}

Output:

4.45 == median([4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5])
4.45 == median([4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5])
4.4 == median([4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3])
4.5 == median([2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5])
3.35 == median([4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2])
5.55 == median([-1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5])
2.3 == median([4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9])
6.6 == median([7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5])
3.35 == median([4.4, 2.3, -1.7, 7.5, 6.6, 0.0])
5.55 == median([6.6, 0.0, 1.9, 8.2, 9.3, 4.5])
4.4 == median([4.4, 2.3, -1.7, 7.5, 6.6])
4.5 == median([0.0, 1.9, 8.2, 9.3, 4.5])
3.35 == median([4.4, 2.3, -1.7, 7.5])
6.35 == median([1.9, 8.2, 9.3, 4.5])
2.3 == median([4.4, 2.3, -1.7])
8.2 == median([8.2, 9.3, 4.5])
3.35 == median([4.4, 2.3])
6.9 == median([9.3, 4.5])
4.4 == median([4.4])
4.5 == median([4.5])
0 == median([])
0 == median([])

Haskell

This uses a quick select algorithm and runs in expected O(n) time.

import Data.List (partition)

nth :: Ord t => [t] -> Int -> t
nth (x:xs) n
  | k == n = x
  | k > n = nth ys n
  | otherwise = nth zs $ n - k - 1
  where
    (ys, zs) = partition (< x) xs
    k = length ys

medianMay :: (Fractional a, Ord a) => [a] -> Maybe a
medianMay xs
  | n < 1 = Nothing
  | even n = Just ((nth xs (div n 2) + nth xs (div n 2 - 1)) / 2.0)
  | otherwise = Just (nth xs (div n 2))
  where
    n = length xs

main :: IO ()
main =
  mapM_
    (printMay . medianMay)
    [[], [7], [5, 3, 4], [5, 4, 2, 3], [3, 4, 1, -8.4, 7.2, 4, 1, 1.2]]
  where
    printMay = maybe (putStrLn "(not defined)") print
Output:
(not defined)
7.0
4.0
3.5
2.1

Or

Library: hstats
> Math.Statistics.median [1,9,2,4]
3.0

HicEst

If the input has an even number of elements, median is the mean of the middle two values:

REAL :: n=10, vec(n)

vec = RAN(1)
SORT(Vector=vec, Sorted=vec) ! in-place Merge-Sort

IF( MOD(n,2) ) THEN  ! odd n
    median = vec( CEILING(n/2) )
ELSE
    median = ( vec(n/2) + vec(n/2 + 1) ) / 2
ENDIF

Icon and Unicon

A quick and dirty solution:

procedure main(args)
    write(median(args))
end

procedure median(A)
    A := sort(A)
    n := *A
    return if n % 2 = 1 then A[n/2+1]
           else (A[n/2]+A[n/2+1])/2.0 | 0  # 0 if empty list
end

Sample outputs:

->am 3 1 4 1 5 9 7 6 3
4
->am 3 1 4 1 5 9 7 6
4.5
->

J

The verb median is available from the stats/base addon and returns the mean of the two middle values for an even number of elements:

  require 'stats/base'
  median 1 9 2 4
3

The definition given in the addon script is:

midpt=: -:@<:@#
median=: -:@(+/)@((<. , >.)@midpt { /:~)

If, for an even number of elements, both values were desired when those two values are distinct, then the following implementation would suffice:

   median=: ~.@(<. , >.)@midpt { /:~
   median 1 9 2 4
2 4

Java

Works with: Java version 1.5+

Sorting:

double median(List<Double> values) {
    /* copy, as to prevent modifying 'values' */
    List<Double> list = new ArrayList<>(values);
    Collections.sort(list);
    /* 'mid' will be truncated */
    int mid = list.size() / 2;
    return switch (list.size() % 2) {
        case 0 -> {
            double valueA = list.get(mid);
            double valueB = list.get(mid + 1);
            yield (valueA + valueB) / 2;
        }
        case 1 -> list.get(mid);
        default -> 0;
    };
}
Works with: Java version 1.5+

Using priority queue (which sorts under the hood):

public static double median2(List<Double> list) {
    PriorityQueue<Double> pq = new PriorityQueue<Double>(list);
    int n = list.size();
    for (int i = 0; i < (n - 1) / 2; i++)
        pq.poll(); // discard first half
    if (n % 2 != 0) // odd length
        return pq.poll();
    else
        return (pq.poll() + pq.poll()) / 2.0;
}
Works with: Java version 1.8+

This version operates on objects rather than primitives and uses abstractions to operate on all of the standard numerics.

@FunctionalInterface
interface MedianFinder<T, R> extends Function<Collection<T>, R> {
    @Override
    R apply(Collection<T> data);
}

class MedianFinderImpl<T, R> implements MedianFinder<T, R> {
    private final Supplier<R> ifEmpty;
    private final Function<T, R> ifOdd;
    private final Function<List<T>, R> ifEven;

    MedianFinderImpl(Supplier<R> ifEmpty, Function<T, R> ifOdd, Function<List<T>, R> ifEven) {
        this.ifEmpty = ifEmpty;
        this.ifOdd = ifOdd;
        this.ifEven = ifEven;
    }

    @Override
    public R apply(Collection<T> data) {
        return Objects.requireNonNull(data, "data must not be null").isEmpty()
                ? ifEmpty.get()
                : (data.size() & 1) == 0
                    ? ifEven.apply(data.stream().sorted()
                          .skip(data.size() / 2 - 1)
                          .limit(2).toList())
                    : ifOdd.apply(data.stream().sorted()
                          .skip(data.size() / 2)
                          .limit(1).findFirst().get());
    }
}

public class MedianOf {
    private static final MedianFinder<Integer, Integer> INTEGERS = new MedianFinderImpl<>(() -> 0, n -> n, pair -> (pair.get(0) + pair.get(1)) / 2);
    private static final MedianFinder<Integer, Float> INTEGERS_AS_FLOAT = new MedianFinderImpl<>(() -> 0f, n -> n * 1f, pair -> (pair.get(0) + pair.get(1)) / 2f);
    private static final MedianFinder<Integer, Double> INTEGERS_AS_DOUBLE = new MedianFinderImpl<>(() -> 0d, n -> n * 1d, pair -> (pair.get(0) + pair.get(1)) / 2d);
    private static final MedianFinder<Float, Float> FLOATS = new MedianFinderImpl<>(() -> 0f, n -> n, pair -> (pair.get(0) + pair.get(1)) / 2);
    private static final MedianFinder<Double, Double> DOUBLES = new MedianFinderImpl<>(() -> 0d, n -> n, pair -> (pair.get(0) + pair.get(1)) / 2);
    private static final MedianFinder<BigInteger, BigInteger> BIG_INTEGERS = new MedianFinderImpl<>(() -> BigInteger.ZERO, n -> n, pair -> pair.get(0).add(pair.get(1)).divide(BigInteger.TWO));
    private static final MedianFinder<BigInteger, BigDecimal> BIG_INTEGERS_AS_BIG_DECIMAL = new MedianFinderImpl<>(() -> BigDecimal.ZERO, BigDecimal::new, pair -> new BigDecimal(pair.get(0).add(pair.get(1))).divide(BigDecimal.valueOf(2), RoundingMode.FLOOR));
    private static final MedianFinder<BigDecimal, BigDecimal> BIG_DECIMALS = new MedianFinderImpl<>(() -> BigDecimal.ZERO, n -> n, pair -> pair.get(0).add(pair.get(1)).divide(BigDecimal.valueOf(2), RoundingMode.FLOOR));

    public static Integer    integers(Collection<Integer> integerCollection) { return INTEGERS.apply(integerCollection); }
    public static Float      integersAsFloat(Collection<Integer> integerCollection) { return INTEGERS_AS_FLOAT.apply(integerCollection); }
    public static Double     integersAsDouble(Collection<Integer> integerCollection) { return INTEGERS_AS_DOUBLE.apply(integerCollection); }
    public static Float      floats(Collection<Float> floatCollection) { return FLOATS.apply(floatCollection); }
    public static Double     doubles(Collection<Double> doubleCollection) { return DOUBLES.apply(doubleCollection); }
    public static BigInteger bigIntegers(Collection<BigInteger> bigIntegerCollection) { return BIG_INTEGERS.apply(bigIntegerCollection); }
    public static BigDecimal bigIntegersAsBigDecimal(Collection<BigInteger> bigIntegerCollection) { return BIG_INTEGERS_AS_BIG_DECIMAL.apply(bigIntegerCollection); }
    public static BigDecimal bigDecimals(Collection<BigDecimal> bigDecimalCollection) { return BIG_DECIMALS.apply(bigDecimalCollection); }
}

JavaScript

ES5

function median(ary) {
    if (ary.length == 0)
        return null;
    ary.sort(function (a,b){return a - b})
    var mid = Math.floor(ary.length / 2);
    if ((ary.length % 2) == 1)  // length is odd
        return ary[mid];
    else 
        return (ary[mid - 1] + ary[mid]) / 2;
}

median([]);   // null
median([5,3,4]);  // 4
median([5,4,2,3]);  // 3.5
median([3,4,1,-8.4,7.2,4,1,1.2]);  // 2.1

ES6

Using a quick select algorithm

Translation of: Haskell
(() => {
    'use strict';

    // median :: [Num] -> Num
    function median(xs) {
        // nth :: [Num] -> Int -> Maybe Num
        let nth = (xxs, n) => {
                if (xxs.length > 0) {
                    let [x, xs] = uncons(xxs), 
                        [ys, zs] = partition(y => y < x, xs),
                        k = ys.length;

                    return k === n ? x : (
                        k > n ? nth(ys, n) : nth(zs, n - k - 1)
                    );
                } else return undefined;
            },
            n = xs.length;

        return even(n) ? (
            (nth(xs, div(n, 2)) + nth(xs, div(n, 2) - 1)) / 2
        ) : nth(xs, div(n, 2));
    }



    // GENERIC

    // partition :: (a -> Bool) -> [a] -> ([a], [a])
    let partition = (p, xs) =>
        xs.reduce((a, x) =>
            p(x) ? [a[0].concat(x), a[1]] : [a[0], a[1].concat(x)], [
                [],
                []
            ]),

        // uncons :: [a] -> Maybe (a, [a])
        uncons = xs => xs.length ? [xs[0], xs.slice(1)] : undefined,

        // even :: Integral a => a -> Bool
        even = n => n % 2 === 0,

        // div :: Num -> Num -> Int
        div = (x, y) => Math.floor(x / y);

    return [
        [],
        [5, 3, 4],
        [5, 4, 2, 3],
        [3, 4, 1, -8.4, 7.2, 4, 1, 1.2]
    ].map(median);
})();
Output:
[
  null,
  4,
  3.5,
  2.1
]

jq

def median:
  length as $length
  | sort as $s
  | if $length == 0 then null
    else ($length / 2 | floor) as $l2 
      | if ($length % 2) == 0 then
          ($s[$l2 - 1] + $s[$l2]) / 2
        else $s[$l2]
        end
  end ;

This definition can be used in a jq program, but to illustrate how it can be used as a command line filter, suppose the definition and the program median are in a file named median.jq, and that the file in.dat contains a sequence of arrays, such as

[4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2] 
[4.1, 7.2, 1.7, 9.3, 4.4, 3.2]

Then invoking the jq program yields a stream of values:

$ jq -f median.jq in.dat
4.4
4.25

Julia

Julia has a built-in median() function

using Statistics
function median2(n)
	s = sort(n)
	len = length(n)
	if len % 2 == 0
		return (s[floor(Int, len / 2) + 1] + s[floor(Int, len / 2)]) / 2
	else
		return  s[floor(Int, len / 2) + 1]
	end
end

a = [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]
b = [4.1, 7.2, 1.7, 9.3, 4.4, 3.2]

@show a b median2(a) median(a) median2(b) median(b)
Output:
a = [4.1,5.6,7.2,1.7,9.3,4.4,3.2]
b = [4.1,7.2,1.7,9.3,4.4,3.2]
median2(a) = 4.4
median(a) = 4.4
median2(b) = 4.25
median(b) = 4.25

K

  med:{a:x@<x; i:(#a)%2; :[(#a)!2; a@i; {(+/x)%#x} a@i,i-1]}
  v:10*6 _draw 0
  v
5.961475 2.025856 7.262835 1.814272 2.281911 4.854716
  med[v]
3.568313
  med[1_ v]
2.281911

An alternate solution which works in the oK implementation using the same dataset v from above and shows both numbers around the median point on even length datasets would be:

med:{a:x@<x; i:_(#a)%2
$[2!#a; a@i; |a@i,i-1]}
med[v]
2.2819 4.8547

Kotlin

Works with: Kotlin version 1.0+
fun median(l: List<Double>) = l.sorted().let { (it[it.size / 2] + it[(it.size - 1) / 2]) / 2 }

fun main(args: Array<String>) {
    median(listOf(5.0, 3.0, 4.0)).let { println(it) }  // 4
    median(listOf(5.0, 4.0, 2.0, 3.0)).let { println(it) }  // 3.5
    median(listOf(3.0, 4.0, 1.0, -8.4, 7.2, 4.0, 1.0, 1.2)).let { println(it) }  // 2.1
}


Lambdatalk

Translation of: 11l
{def median
 {lambda {:s}
  {let { {:a {A.sort! < {A.new :s}}}
         {:len {S.length :s}}
       } {* 0.5 {+ {A.get {floor {/ {- :len 1} 2}} :a}
                   {A.get {floor {/ :len 2}} :a} }} }}}
-> median

{median 4.1 5.6 7.2 1.7 9.3 4.4 3.2}
-> 4.4
{median 4.1 7.2 1.7 9.3 4.4 3.2} 
-> 4.25

Lasso

can't use Lasso's built in median method because that takes 3 values, not an array of indeterminate length

Lasso's built in function is "median( value_1, value_2, value_3 )"

define median_ext(a::array) => {
	#a->sort

	if(#a->size % 2) => {
		// odd numbered element array, pick middle
		return #a->get(#a->size / 2 + 1)

	else
		// even number elements in array
		return (#a->get(#a->size / 2) + #a->get(#a->size / 2 + 1)) / 2.0
	}
}

median_ext(array(3,2,7,6)) // 4.5
median_ext(array(3,2,9,7,6)) // 6

Liberty BASIC

    dim a( 100), b( 100)    '   assumes we will not have vectors of more terms...

    a$ ="4.1,5.6,7.2,1.7,9.3,4.4,3.2"
    print "Median is "; median( a$)        '   4.4   7 terms
    print
    a$ ="4.1,7.2,1.7,9.3,4.4,3.2"
    print "Median  is "; median( a$)        '   4.25  6 terms
    print
    a$ ="4.1,4,1.2,6.235,7868.33"   '   4.1
    print "Median of "; a$; " is "; median( a$)
    print
    a$ ="1,5,3,2,4"             '   3
    print "Median of "; a$; " is "; median( a$)
    print
    a$ ="1,5,3,6,4,2"          '   3.5
    print "Median of "; a$; " is "; median( a$)
    print
    a$ ="4.4,2.3,-1.7,7.5,6.6,0.0,1.9,8.2,9.3,4.5" '   4.45
    print "Median of "; a$; " is "; median( a$)

    end

    function median( a$)
        i =1
        do
            v$     =word$( a$, i, ",")
            if v$ ="" then exit do
            print v$,
            a( i)  =val( v$)
            i      =i +1
        loop until 0
        print

        sort a(), 1, i -1

        for j =1 to i -1
            print a( j),
        next j
        print

        middle    =( i -1) /2
        intmiddle =int( middle)
        if middle <>intmiddle then median= a( 1 +intmiddle) else median =( a( intmiddle) +a( intmiddle +1)) /2
    end function
4.1 5.6 7.2 1.7 9.3 4.4 3.2
Median is 4.4

4.1 7.2 1.7 9.3 4.4 3.2
Median is 4.25

4.1 4 1.2 6.235 7868.33
Median of 4.1,4,1.2,6.235,7868.33 is 4.1

1 5 3 2 4
Median of 1,5,3,2,4 is 3

1 5 3 6 4 2
Median of 1,5,3,6,4,2 is 3.5

4.4 2.3 -1.7 7.5 6.6 0.0 1.9 8.2 9.3 4.5
Median of 4.4,2.3,-1.7,7.5,6.6,0.0,1.9,8.2,9.3,4.5 is 4.45

Lingo

on median (numlist)
    -- numlist = numlist.duplicate() -- if input list should not be altered
    numlist.sort()
    if numlist.count mod 2 then
        return numlist[numlist.count/2+1]
    else
        return (numlist[numlist.count/2]+numlist[numlist.count/2+1])/2.0
    end if
end

LiveCode

LC has median as a built-in function

put median("4.1,5.6,7.2,1.7,9.3,4.4,3.2") & "," & median("4.1,7.2,1.7,9.3,4.4,3.2")
returns 4.4, 4.25

To make our own, we need own own floor function first

function floor n
    if n < 0 then
        return (trunc(n) - 1)
    else
        return trunc(n)
    end if
end floor

function median2 x
    local n, m
    set itemdelimiter to comma
    sort items of x ascending numeric
    put the number of items of x into n
    put floor(n / 2) into m
    if n mod 2 is 0 then
        return (item m of x + item (m + 1) of x) / 2
    else
        return item (m + 1) of x
    end if
end median2

returns the same as the built-in median, viz. 
put median2("4.1,5.6,7.2,1.7,9.3,4.4,3.2") & "," & median2("4.1,7.2,1.7,9.3,4.4,3.2")
4.4,4.25

LSL

integer MAX_ELEMENTS = 10;
integer MAX_VALUE = 100;
default {
    state_entry() {
        list lst = [];
        integer x = 0;
        for(x=0 ; x<MAX_ELEMENTS ; x++) {
            lst += llFrand(MAX_VALUE);
        }
        llOwnerSay("lst=["+llList2CSV(lst)+"]");
        llOwnerSay("Geometric Mean: "+(string)llListStatistics(LIST_STAT_GEOMETRIC_MEAN, lst));
        llOwnerSay("           Max: "+(string)llListStatistics(LIST_STAT_MAX, lst));
        llOwnerSay("          Mean: "+(string)llListStatistics(LIST_STAT_MEAN, lst));
        llOwnerSay("        Median: "+(string)llListStatistics(LIST_STAT_MEDIAN, lst));
        llOwnerSay("           Min: "+(string)llListStatistics(LIST_STAT_MIN, lst));
        llOwnerSay("     Num Count: "+(string)llListStatistics(LIST_STAT_NUM_COUNT, lst));
        llOwnerSay("         Range: "+(string)llListStatistics(LIST_STAT_RANGE, lst));
        llOwnerSay("       Std Dev: "+(string)llListStatistics(LIST_STAT_STD_DEV, lst));
        llOwnerSay("           Sum: "+(string)llListStatistics(LIST_STAT_SUM, lst));
        llOwnerSay("   Sum Squares: "+(string)llListStatistics(LIST_STAT_SUM_SQUARES, lst));
    }
}

Output:

lst=[23.815209, 85.890704, 10.811144, 31.522696, 54.619416, 12.211729, 42.964463, 87.367889, 7.106129, 18.711078]
Geometric Mean:    27.325070
           Max:    87.367889
          Mean:    37.502046
        Median:    27.668953
           Min:     7.106129
     Num Count:    10.000000
         Range:    80.261761
       Std Dev:    29.819840
           Sum:   375.020458
   Sum Squares: 22067.040048

Lua

function median (numlist)
    if type(numlist) ~= 'table' then return numlist end
    table.sort(numlist)
    if #numlist %2 == 0 then return (numlist[#numlist/2] + numlist[#numlist/2+1]) / 2 end
    return numlist[math.ceil(#numlist/2)]
end

print(median({4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2}))
print(median({4.1, 7.2, 1.7, 9.3, 4.4, 3.2}))

Maple

Builtin

This works for numeric lists or arrays, and is designed for large data sets.

> Statistics:-Median( [ 1, 5, 3, 2, 4 ] );
                                   3.

> Statistics:-Median( [ 1, 5, 3, 6, 2, 4 ] );
                            3.50000000000000

Using a sort

This solution can handle exact numeric inputs. Instead of inputting a container of some kind, it simply finds the median of its arguments.

median1 := proc()
        local L := sort( [ args ] );
        ( L[ iquo( 1 + nargs, 2 ) ] + L[ 1 + iquo( nargs, 2 ) ] ) / 2
end proc:

For example:

> median1( 1, 5, 3, 2, 4 ); # 3
                                   3

> median1( 1, 5, 3, 6, 4, 2 ); # 7/2
                                  7/2

Mathematica / Wolfram Language

Built-in function:

Median[{1, 5, 3, 2, 4}]
Median[{1, 5, 3, 6, 4, 2}]
Output:
3
7/2

Custom function:

mymedian[x_List]:=Module[{t=Sort[x],L=Length[x]},
 If[Mod[L,2]==0,
  (t[[L/2]]+t[[L/2+1]])/2
 ,
  t[[(L+1)/2]]
 ]
]

Example of custom function:

mymedian[{1, 5, 3, 2, 4}]
mymedian[{1, 5, 3, 6, 4, 2}]
Output:
3
7/2

MATLAB

If the input has an even number of elements, function returns the mean of the middle two values:

function medianValue = findmedian(setOfValues)    
   medianValue = median(setOfValues);
end

Maxima

/* built-in */
median([41, 56, 72, 17, 93, 44, 32]);  /* 44 */
median([41, 72, 17, 93, 44, 32]);      /* 85/2 */

min

('> sort med) ^median

(4.1 5.6 7.2 1.7 9.3 4.4 3.2) median puts!
(4.1 7.2 1.7 9.3 4.4 3.2) median puts!
Output:
4.4
4.25

MiniScript

list.median = function()
    self.sort
    m = floor(self.len/2)
    if self.len % 2 then return self[m]
    return (self[m] + self[m-1]) * 0.5
end function
    
print [41, 56, 72, 17, 93, 44, 32].median
print [41, 72, 17, 93, 44, 32].median
Output:
44
42.5

MUMPS

MEDIAN(X)
 ;X is assumed to be a list of numbers separated by "^"
 ;I is a loop index
 ;L is the length of X
 ;Y is a new array
 QUIT:'$DATA(X) "No data"
 QUIT:X="" "Empty Set"
 NEW I,ODD,L,Y
 SET L=$LENGTH(X,"^"),ODD=L#2,I=1
 ;The values in the vector are used as indices for a new array Y, which sorts them
 FOR  QUIT:I>L  SET Y($PIECE(X,"^",I))=1,I=I+1
 ;Go to the median index, or the lesser of the middle if there is an even number of elements
 SET J="" FOR I=1:1:$SELECT(ODD:L\2+1,'ODD:L/2) SET J=$ORDER(Y(J))
 QUIT $SELECT(ODD:J,'ODD:(J+$ORDER(Y(J)))/2)
USER>W $$MEDIAN^ROSETTA("-1.3^2.43^3.14^17^2E-3")
3.14
USER>W $$MEDIAN^ROSETTA("-1.3^2.43^3.14^17^2E-3^4")
3.57
USER>W $$MEDIAN^ROSETTA("")
Empty Set
USER>W $$MEDIAN^ROSETTA
No data

Nanoquery

Translation of: Python
import sort

def median(aray)
	srtd = sort(aray)
	alen = len(srtd)
	return 0.5*( srtd[int(alen-1/2)] + srtd[int(alen/2)])
end

a = {4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2}
println a + " " + median(a)
a = {4.1, 7.2, 1.7, 9.3, 4.4, 3.2}
println a + " " + median(a)

NetRexx

Translation of: Java
/* NetRexx */
options replace format comments java crossref symbols nobinary

class RAvgMedian00 public

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method median(lvector = java.util.List) public static returns Rexx
    cvector = ArrayList(lvector) -- make a copy of input to ensure it's contents are preserved
    Collections.sort(cvector, RAvgMedian00.RexxComparator())
    kVal = ((Rexx cvector.get(cvector.size() % 2)) + (Rexx cvector.get((cvector.size() - 1) % 2))) / 2
    return kVal

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method median(rvector = Rexx[]) public static returns Rexx
    return median(ArrayList(Arrays.asList(rvector)))

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method show_median(lvector = java.util.List) public static returns Rexx
    mVal = median(lvector)
    say 'Meadian:' mVal.format(10, 6, 3, 6, 's')', Vector:' (Rexx lvector).space(0)
    return mVal

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method show_median(rvector = Rexx[]) public static returns Rexx
    return show_median(ArrayList(Arrays.asList(rvector)))

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method run_samples() public static
    show_median([Rexx 10.0])                                                   -- 10.0
    show_median([Rexx 10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0])      -- 5.5
    show_median([Rexx 9, 8, 7, 6, 5, 4, 3, 2, 1])                              -- 5.0
    show_median([Rexx 1.0, 9, 2.0, 4.0])                                       -- 3.0
    show_median([Rexx 3.0, 1, 4, 1.0, 5.0, 9, 7.0, 6.0])                       -- 4.5
    show_median([Rexx 3, 4, 1, -8.4, 7.2, 4, 1, 1.2])                          -- 2.1
    show_median([Rexx -1.2345678e+99, 2.3e+700])                               -- 1.15e+700
    show_median([Rexx 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2])                      -- 4.4
    show_median([Rexx 4.1, 7.2, 1.7, 9.3, 4.4, 3.2])                           -- 4.25
    show_median([Rexx 28.207, 74.916, 51.695, 72.486, 51.118, 3.241, 73.807])  -- 51.695
    show_median([Rexx 27.984, 89.172, 0.250, 66.316, 41.805, 60.043])          -- 50.924
    show_median([Rexx 5.1, 2.6, 6.2, 8.8, 4.6, 4.1])                           -- 4.85
    show_median([Rexx 5.1, 2.6, 8.8, 4.6, 4.1])                                -- 4.6
    show_median([Rexx 4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5])      -- 4.45
    show_median([Rexx 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0.11])        -- 3.0
    show_median([Rexx 10, 20, 30, 40, 50, -100, 4.7, -11e+2])                  -- 15.0
    show_median([Rexx 9.3, -2.0, 4.0, 7.3, 8.1, 4.1, -6.3, 4.2, -1.0, -8.4])   -- 4.05
    show_median([Rexx 8.3, -3.6, 5.7, 2.3, 9.3, 5.4, -2.3, 6.3, 9.9])          -- 5.7
    return

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method main(args = String[]) public static
    run_samples()
    return

-- =============================================================================
class RAvgMedian00.RexxComparator implements Comparator

  -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  method compare(i1=Object, i2=Object) public returns int 
    i = Rexx i1 
    j = Rexx i2 

    if i < j then return -1 
    if i > j then return +1 
    else return 0

Output:

Meadian:         10.000000     , Vector: [10.0]
Meadian:          5.500000     , Vector: [10.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0]
Meadian:          5.000000     , Vector: [9,8,7,6,5,4,3,2,1]
Meadian:          3.000000     , Vector: [1.0,9,2.0,4.0]
Meadian:          4.500000     , Vector: [3.0,1,4,1.0,5.0,9,7.0,6.0]
Meadian:          2.100000     , Vector: [3,4,1,-8.4,7.2,4,1,1.2]
Meadian:          1.150000E+700, Vector: [-1.2345678E+99,2.3e+700]
Meadian:          4.400000     , Vector: [4.1,5.6,7.2,1.7,9.3,4.4,3.2]
Meadian:          4.250000     , Vector: [4.1,7.2,1.7,9.3,4.4,3.2]
Meadian:         51.695000     , Vector: [28.207,74.916,51.695,72.486,51.118,3.241,73.807]
Meadian:         50.924000     , Vector: [27.984,89.172,0.250,66.316,41.805,60.043]
Meadian:          4.850000     , Vector: [5.1,2.6,6.2,8.8,4.6,4.1]
Meadian:          4.600000     , Vector: [5.1,2.6,8.8,4.6,4.1]
Meadian:          4.450000     , Vector: [4.4,2.3,-1.7,7.5,6.6,0.0,1.9,8.2,9.3,4.5]
Meadian:          3.000000     , Vector: [10,9,8,7,6,5,4,3,2,1,0,0,0,0,0.11]
Meadian:         15.000000     , Vector: [10,20,30,40,50,-100,4.7,-1100]
Meadian:          4.050000     , Vector: [9.3,-2.0,4.0,7.3,8.1,4.1,-6.3,4.2,-1.0,-8.4]
Meadian:          5.700000     , Vector: [8.3,-3.6,5.7,2.3,9.3,5.4,-2.3,6.3,9.9]

NewLISP

; median.lsp
; oofoe 2012-01-25

(define (median lst)
  (sort lst) ; Sorts in place.
  (if (empty? lst)
      nil
    (letn ((n (length lst))
           (h (/ (- n 1) 2)))
          (if (zero? (mod n 2))
              (div (add (lst h) (lst (+ h 1))) 2)
            (lst h))
          )))


(define (test lst) (println lst " -> " (median lst)))

(test '())
(test '(5 3 4))
(test '(5 4 2 3))
(test '(3 4 1 -8.4 7.2 4 1 1.2))

(exit)

Sample output:

() -> nil
(5 3 4) -> 4
(5 4 2 3) -> 3.5
(3 4 1 -8.4 7.2 4 1 1.2) -> 2.1

Nim

Translation of: Python
import algorithm, strutils
 
proc median(xs: seq[float]): float =
  var ys = xs
  sort(ys, system.cmp[float])
  0.5 * (ys[ys.high div 2] + ys[ys.len div 2]) 
 
var a = @[4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]
echo formatFloat(median(a), precision = 0)
a = @[4.1, 7.2, 1.7, 9.3, 4.4, 3.2]
echo formatFloat(median(a), precision = 0)

Example Output:

4.4
4.25

Nu

Works with: Nushell version 0.96.1
[7 8 9 6 5 2] | math median
Output:
6.5

Oberon-2

Oxford Oberon-2

MODULE Median;
IMPORT Out;
CONST
	MAXSIZE = 100;
	
PROCEDURE Partition(VAR a: ARRAY OF REAL; left, right: INTEGER): INTEGER;
VAR
	pValue,aux: REAL;
	store,i,pivot: INTEGER;
BEGIN
	pivot := right;
	pValue := a[pivot];
	aux := a[right];a[right] := a[pivot];a[pivot] := aux; (* a[pivot] <-> a[right] *)
	store := left;
	FOR i := left TO right -1 DO 
		IF a[i] <= pValue THEN
			aux := a[store];a[store] := a[i];a[i]:=aux;
			INC(store)
		END
	END;
	aux := a[right];a[right] := a[store]; a[store] := aux;
	RETURN store
END Partition;

(* QuickSelect algorithm *)
PROCEDURE Select(a: ARRAY OF REAL; left,right,k: INTEGER;VAR r: REAL);
VAR
	pIndex, pDist : INTEGER;
BEGIN
	IF left = right THEN r := a[left]; RETURN END;
	pIndex := Partition(a,left,right);
	pDist := pIndex - left + 1;
	IF pDist = k THEN
		r := a[pIndex];RETURN
	ELSIF k < pDist THEN
		Select(a,left, pIndex - 1, k, r)
	ELSE
		Select(a,pIndex + 1, right, k - pDist, r)
	END
END Select;

PROCEDURE Median(a: ARRAY OF REAL;left,right: INTEGER): REAL;
VAR
	idx,len : INTEGER;
	r1,r2 : REAL;
BEGIN
	len := right - left + 1;
	idx := len DIV 2 + 1;
	r1 := 0.0;r2 := 0.0;
	Select(a,left,right,idx,r1);
	IF ODD(len) THEN RETURN r1 END;
	Select(a,left,right,idx - 1,r2);
	RETURN (r1 + r2) / 2;
END Median;


VAR
	ary: ARRAY MAXSIZE OF REAL;
	r: REAL;
BEGIN
	r := 0.0;
	Out.Fixed(Median(ary,0,0),4,2);Out.Ln;	(* empty *)
	ary[0] := 5;
	ary[1] := 3;
	ary[2] := 4;
	Out.Fixed(Median(ary,0,2),4,2);Out.Ln;	
	ary[0] := 5;
	ary[1] := 4;
	ary[2] := 2;
	ary[3] := 3;
	Out.Fixed(Median(ary,0,3),4,2);Out.Ln;	
	ary[0] := 3;
	ary[1] := 4;
	ary[2] := 1;
	ary[3] := -8.4;
	ary[4] := 7.2;
	ary[5] := 4;
	ary[6] := 1;
	ary[7] := 1.2;
	Out.Fixed(Median(ary,0,7),4,2);Out.Ln;	
END Median.
Output:
0.00
4.00
3.50
2.10

Objeck

use Structure;

bundle Default {
  class Median {
    function : Main(args : String[]) ~ Nil {
      numbers := FloatVector->New([4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]);
      DoMedian(numbers)->PrintLine();

      numbers := FloatVector->New([4.1, 7.2, 1.7, 9.3, 4.4, 3.2]);
      DoMedian(numbers)->PrintLine();
    }

    function : native : DoMedian(numbers : FloatVector) ~ Float {
      if(numbers->Size() = 0) {
        return 0.0;
      }
      else if(numbers->Size() = 1) {
        return numbers->Get(0);
      };
      
      numbers->Sort();

      i := numbers->Size() / 2;
      if(numbers->Size() % 2 = 0) {
        return (numbers->Get(i - 1) + numbers->Get(i)) / 2.0;              
      };
      
      return numbers->Get(i);
    }
  }
}

OCaml

(* note: this modifies the input array *)
let median array =
  let len = Array.length array in
    Array.sort compare array;
    (array.((len-1)/2) +. array.(len/2)) /. 2.0;;

let a = [|4.1; 5.6; 7.2; 1.7; 9.3; 4.4; 3.2|];;
median a;;
let a = [|4.1; 7.2; 1.7; 9.3; 4.4; 3.2|];;
median a;;

Octave

Of course Octave has its own median function we can use to check our implementation. The Octave's median function, however, does not handle the case you pass in a void vector.

function y = median2(v)
  if (numel(v) < 1)
    y = NA;
  else
    sv = sort(v);
    l = numel(v);
    if ( mod(l, 2) == 0 )
      y = (sv(floor(l/2)+1) + sv(floor(l/2)))/2;
    else
      y = sv(floor(l/2)+1);
    endif
  endif
endfunction

a = [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2];
b = [4.1, 7.2, 1.7, 9.3, 4.4, 3.2];

disp(median2(a))   % 4.4
disp(median(a))
disp(median2(b))   % 4.25   
disp(median(b))

ooRexx

call testMedian .array~of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
call testMedian .array~of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, .11)
call testMedian .array~of(10, 20, 30, 40, 50, -100, 4.7, -11e2)
call testMedian .array~new

::routine testMedian
  use arg numbers
  say "numbers =" numbers~toString("l", ", ")
  say "median =" median(numbers)
  say

::routine median
  use arg numbers

  if numbers~isempty then return 0
  -- make a copy so the sort does not alter the
  -- original set.  This also means this will
  -- work with lists and queues as well
  numbers = numbers~makearray

  -- sort and return the middle element
  numbers~sortWith(.numbercomparator~new)
  size = numbers~items
  -- this handles the odd value too
  return numbers[size%2 + size//2]


-- a custom comparator that sorts strings as numeric values rather than
-- strings
::class numberComparator subclass comparator
::method compare
  use strict arg left, right
  -- perform the comparison on the names.  By subtracting
  -- the two and returning the sign, we give the expected
  -- results for the compares
  return (left - right)~sign

Oz

declare
  fun {Median Xs}
     Len = {Length Xs}
     Mid = Len div 2 + 1 %% 1-based index
     Sorted = {Sort Xs Value.'<'}
  in
     if {IsOdd Len} then {Nth Sorted Mid}
     else ({Nth Sorted Mid} + {Nth Sorted Mid-1}) / 2.0
     end
  end
in
  {Show {Median [4.1 5.6 7.2 1.7 9.3 4.4 3.2]}}
  {Show {Median [4.1 7.2 1.7 9.3 4.4 3.2]}}

PARI/GP

Sorting solution.

median(v)={
  vecsort(v)[#v\2]
};

Linear-time solution, mostly proof-of-concept but perhaps suitable for large lists.

BFPRT(v,k=#v\2)={
	if(#v<15, return(vecsort(v)[k]));
	my(u=List(),pivot,left=List(),right=List());
	forstep(i=1,#v-4,5,
		listput(u,BFPRT([v[i],v[i+1],v[i+2],v[i+3],v[i+4]]))
	);
	pivot=BFPRT(Vec(u));
	u=0;
	for(i=1,#v,
		if(v[i]<pivot,
			listput(left,v[i])
		,
			listput(right,v[i])
		)
	);
	if(k>#left,
		BFPRT(right, k-#left)
	,
		BFPRT(left, k)
	)
};

Pascal

Works with: Free_Pascal
Program AveragesMedian(output);

type
  TDoubleArray = array of double;
 
procedure bubbleSort(var list: TDoubleArray);
var
  i, j, n: integer;
  t: double;
begin
  n := length(list);
  for i := n downto 2 do
    for j := 0 to i - 1 do
      if list[j] > list[j + 1] then
      begin
        t := list[j];
        list[j] := list[j + 1];
        list[j + 1] := t;
      end;
end;

function Median(aArray: TDoubleArray): double;
var
  lMiddleIndex: integer;
begin
  bubbleSort(aArray);
  lMiddleIndex := (high(aArray) - low(aArray)) div 2;
  if Odd(Length(aArray)) then
    Median := aArray[lMiddleIndex + 1]
  else
    Median := (aArray[lMiddleIndex + 1] + aArray[lMiddleIndex]) / 2;
end;

var
  A: TDoubleArray;
  i: integer;

begin
  randomize;
  setlength(A, 7);
  for i := low(A) to high(A) do
  begin
    A[i] := 100 * random;
    write (A[i]:7:3, ' ');
  end;
  writeln;
  writeln('Median: ', Median(A):7:3);

  setlength(A, 6);
  for i := low(A) to high(A) do
  begin
    A[i] := 100 * random;
    write (A[i]:7:3, ' ');
  end;
  writeln;
  writeln('Median: ', Median(A):7:3);
end.

Output:

% ./Median
 28.207  74.916  51.695  72.486  51.118   3.241  73.807 
Median:  51.695
 27.984  89.172   0.250  66.316  41.805  60.043 
Median:  50.924

PascalABC.NET

##
function median(a: array of real): real;
begin
  var asort := a.Sorted.ToArray;
  var alen := a.Length;
  result := (asort[(alen - 1) div 2] + asort[alen div 2]) / 2;
end;

var a := arr(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2);
println(a, 'median', median(a));
a := arr(4.1, 7.2, 1.7, 9.3, 4.4, 3.2);
println(a, 'median', median(a));
Output:
[4.1,5.6,7.2,1.7,9.3,4.4,3.2] median 4.4
[4.1,7.2,1.7,9.3,4.4,3.2] median 4.25

Perl

Translation of: Python
sub median {
  my @a = sort {$a <=> $b} @_;
  return ($a[$#a/2] + $a[@a/2]) / 2;
}

Phix

The obvious simple way:

with javascript_semantics
function median(sequence s)
    atom res=0
    integer l = length(s), k = floor((l+1)/2)
    if l then
        s = sort(s)
        res = s[k]
        if remainder(l,2)=0 then
            res = (res+s[k+1])/2
        end if
    end if
    return res
end function

It is also possible to use the quick_select routine for a small (20%) performance improvement, which as suggested below may with luck be magnified by retaining any partially sorted results.

with javascript_semantics
function medianq(sequence s)
    atom res=0, tmp
    integer l = length(s), k = floor((l+1)/2)
    if l then
        {s,res} = quick_select(s,k)
        if remainder(l,2)=0 then
            {s,tmp} = quick_select(s,k+1)
            res = (res+tmp)/2
        end if
    end if
    return res  -- (or perhaps return {s,res})
end function

Phixmonti

include ..\Utilitys.pmt

def median  /# l -- n #/
    sort len 2 / >ps
    tps .5 + int 2 slice nip
    ps> dup int != if
        1 get nip
    else
        sum 2 /
    endif
enddef

( 4.1 5.6 7.2 1.7 9.3 4.4 3.2 ) median ?
( 4.1 7.2 1.7 9.3 4.4 3.2 ) median ?

PHP

This solution uses the sorting method of finding the median.

function median($arr)
{
    sort($arr);
    $count = count($arr); //count the number of values in array
    $middleval = floor(($count-1)/2); // find the middle value, or the lowest middle value
    if ($count % 2) { // odd number, middle is the median
        $median = $arr[$middleval];
    } else { // even number, calculate avg of 2 medians
        $low = $arr[$middleval];
        $high = $arr[$middleval+1];
        $median = (($low+$high)/2);
    }
    return $median;
}

echo median(array(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2)) . "\n";  // 4.4
echo median(array(4.1, 7.2, 1.7, 9.3, 4.4, 3.2)) . "\n";       // 4.25

Picat

go => 
   Lists = [
             [1.121,10.3223,3.41,12.1,0.01],
             1..10,
             1..11,
             [3],
             [3,4],             
             [],
             [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2],
             [4.1, 7.2, 1.7, 9.3, 4.4, 3.2],
             [5.1, 2.6, 6.2, 8.8, 4.6, 4.1],
             [5.1, 2.6, 8.8, 4.6, 4.1]],

   foreach(List in Lists) 
      println([List, median=median(List)])
   end,

   nl.

median([])  = undef.
median([X]) = X.
median(L)   = cond(Len mod 2 == 1, LL[H+1], avg([LL[H],LL[H+1]])) =>
   Len = L.length,
   H = Len // 2,
   LL = sort(L).
Output:
[[1.121,10.3223,3.41,12.1,0.01],median = 3.41]
[[1,2,3,4,5,6,7,8,9,10],median = 5.5]
[[1,2,3,4,5,6,7,8,9,10,11],median = 6]
[[3],median = 3]
[[3,4],median = 3.5]
[[],median = undef]
[[4.1,5.6,7.2,1.7,9.300000000000001,4.4,3.2],median = 4.4]
[[4.1,7.2,1.7,9.300000000000001,4.4,3.2],median = 4.25]
[[5.1,2.6,6.2,8.800000000000001,4.6,4.1],median = 4.85]
[[5.1,2.6,8.800000000000001,4.6,4.1],median = 4.6]

PicoLisp

(de median (Lst)
   (let N (length Lst)
      (if (bit? 1 N)
         (get (sort Lst) (/ (inc N) 2))
         (setq Lst (nth (sort Lst) (/ N 2)))
         (/ (+ (car Lst) (cadr Lst)) 2) ) ) )

(scl 2)
(prinl (round (median (1.0 2.0 3.0))))
(prinl (round (median (1.0 2.0 3.0 4.0))))
(prinl (round (median (5.1 2.6 6.2 8.8 4.6 4.1))))
(prinl (round (median (5.1 2.6 8.8 4.6 4.1))))

Output:

2.00
2.50
4.85
4.60

PL/I

call sort(A);
n = dimension(A,1);
if iand(n,1) = 1 then /* an odd number of elements */
   median = A(n/2);
else                  /* an even number of elements */
   median = (a(n/2) + a(trunc(n/2)+1) )/2;

PowerShell

This function returns an object containing the minimal amount of statistical data, including Median, and could be modified to take input directly from the pipeline.

All statistical properties could easily be added to the output object.

function Measure-Data
{
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    Param
    (
        [Parameter(Mandatory=$true,
                   Position=0)]
        [double[]]
        $Data
    )

    Begin
    {
        function Get-Mode ([double[]]$Data)
        {
            if ($Data.Count -gt ($Data | Select-Object -Unique).Count)
            {
                $groups = $Data | Group-Object | Sort-Object -Property Count -Descending

                return ($groups | Where-Object {[double]$_.Count -eq [double]$groups[0].Count}).Name | ForEach-Object {[double]$_}
            }
            else
            {
                return $null
            }
        }

        function Get-StandardDeviation ([double[]]$Data)
        {
            $variance = 0            
            $average  = $Data | Measure-Object -Average | Select-Object -Property Count, Average

            foreach ($number in $Data)
            {            
                $variance +=  [Math]::Pow(($number - $average.Average),2)
            }

            return [Math]::Sqrt($variance / ($average.Count-1))
        }

        function Get-Median ([double[]]$Data)
        {
            if ($Data.Count % 2)
            {
                return $Data[[Math]::Floor($Data.Count/2)]
            }
            else
            {
                return ($Data[$Data.Count/2], $Data[$Data.Count/2-1] | Measure-Object -Average).Average
            }
        }
    }
    Process
    {
        $Data = $Data | Sort-Object

        $Data | Measure-Object -Maximum -Minimum -Sum -Average |
                Select-Object -Property Count,
                                        Sum,
                                        Minimum,
                                        Maximum,
                                        @{Name='Range'; Expression={$_.Maximum - $_.Minimum}},
                                        @{Name='Mean' ; Expression={$_.Average}} |
                Add-Member -MemberType NoteProperty -Name Median            -Value (Get-Median $Data)            -PassThru |
                Add-Member -MemberType NoteProperty -Name StandardDeviation -Value (Get-StandardDeviation $Data) -PassThru |
                Add-Member -MemberType NoteProperty -Name Mode              -Value (Get-Mode $Data)              -PassThru
    }
}
$statistics = Measure-Data 4, 5, 6, 7, 7, 7, 8, 1, 1, 1, 2, 3
$statistics
Output:
Count             : 12
Sum               : 52
Minimum           : 1
Maximum           : 8
Range             : 7
Mean              : 4.33333333333333
Median            : 4.5
StandardDeviation : 2.67423169368609
Mode              : {1, 7}

Median only:

$statistics.Median
Output:
4.5

Processing

void setup() {
  float[] numbers = {3.1, 4.1, 5.9, 2.6, 5.3, 5.8};
  println(median(numbers));
  numbers = shorten(numbers);
  println(median(numbers));
}
 
float median(float[] nums) {
  nums = sort(nums);
  float median = (nums[(nums.length - 1) / 2] + nums[nums.length / 2]) / 2.0;
  return median;
}
Output:
4.7
4.1

Prolog

median(L, Z) :-
    length(L, Length),
    I is Length div 2,
    Rem is Length rem 2,
    msort(L, S),
    maplist(sumlist, [[I, Rem], [I, 1]], Mid),
    maplist(nth1, Mid, [S, S], X),
    sumlist(X, Y),
    Z is Y/2.

Pure

Inspired by the Haskell version.

median x = (/(2-rem)) $ foldl1 (+) $ take (2-rem) $ drop (mid-(1-rem)) $ sort (<=) x
    when len = # x;
         mid = len div 2;
         rem = len mod 2;
         end;

Output:

> median [1, 3, 5];
3.0
> median [1, 2, 3, 4];
2.5

PureBasic

Procedure.d median(Array values.d(1), length.i)
  If length = 0 : ProcedureReturn 0.0 : EndIf
  SortArray(values(), #PB_Sort_Ascending)
  If length % 2
    ProcedureReturn values(length / 2)
  EndIf
  ProcedureReturn 0.5 * (values(length / 2 - 1) + values(length / 2))
EndProcedure

Procedure.i readArray(Array values.d(1))
  Protected length.i, i.i
  Read.i length
  ReDim values(length - 1)
  For i = 0 To length - 1
    Read.d values(i)
  Next
  ProcedureReturn i
EndProcedure

Dim floats.d(0)
Restore array1
length.i = readArray(floats())
Debug median(floats(), length)
Restore array2
length.i = readArray(floats())
Debug median(floats(), length)

DataSection
  array1:
    Data.i 7
    Data.d 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2
  array2:
    Data.i 6
    Data.d 4.1, 7.2, 1.7, 9.3, 4.4, 3.2
EndDataSection

Python

def median(aray):
    srtd = sorted(aray)
    alen = len(srtd)
    return 0.5*( srtd[(alen-1)//2] + srtd[alen//2])

a = (4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2)
print a, median(a)
a = (4.1, 7.2, 1.7, 9.3, 4.4, 3.2)
print a, median(a)

R

R has its built-in median function.

Translation of: Octave
omedian <- function(v) {
  if ( length(v) < 1 )
    NA
  else {
    sv <- sort(v)
    l <- length(sv)
    if ( l %% 2 == 0 )
      (sv[floor(l/2)+1] + sv[floor(l/2)])/2
    else
      sv[floor(l/2)+1]
  }
}

a <- c(4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2)
b <- c(4.1, 7.2, 1.7, 9.3, 4.4, 3.2)

print(median(a))   # 4.4
print(omedian(a))
print(median(b))   # 4.25
print(omedian(b))

Racket

#lang racket
(define (median numbers)
  (define sorted (list->vector (sort (vector->list numbers) <)))
  (define count (vector-length numbers))
  (if (zero? count)
      #f
      (/ (+ (vector-ref sorted (floor (/ (sub1 count) 2)))
            (vector-ref sorted (floor (/ count 2))))
         2)))

(median '#(5 3 4)) ;; 4
(median '#()) ;; #f
(median '#(5 4 2 3)) ;; 7/2
(median '#(3 4 1 -8.4 7.2 4 1 1.2)) ;; 2.1

Raku

(formerly Perl 6)

Works with: Rakudo version 2016.08
sub median {
  my @a = sort @_;
  return (@a[(*-1) div 2] + @a[* div 2]) / 2;
}

Notes:

  • The div operator does integer division. The / operator (rational number division) would work too, since the array subscript automatically coerces to Int, but using div is more explicit (i.e. clearer to readers) as well as faster, and thus recommended in cases like this.
  • The * inside the subscript stands for the array's length (see documentation).


In a slightly more compact way:

sub median { @_.sort[(*-1)/2, */2].sum / 2 }

REBOL

median: func [
    "Returns the midpoint value in a series of numbers; half the values are above, half are below."
    block [any-block!]
    /local len mid
][
    if empty? block [return none]
    block: sort copy block
    len: length? block
    mid: to integer! len / 2
    either odd? len [
        pick block add 1 mid
    ][
        (block/:mid) + (pick block add 1 mid) / 2
    ]
]

ReScript

let median = (arr) =>
{
    let float_compare = (a, b) => {
      let diff = a -. b
      if diff == 0.0 { 0 } else
      if diff > 0.0 { 1 } else { -1 }
    }
    let _ = Js.Array2.sortInPlaceWith(arr, float_compare)
    let count = Js.Array.length(arr)
    // find the middle value, or the lowest middle value
    let middleval = ((count - 1) / 2)
    let median =
      if (mod(count, 2) != 0) { // odd number, middle is the median
          arr[middleval]
      } else { // even number, calculate avg of 2 medians
          let low = arr[middleval]
          let high = arr[middleval+1]
          ((low +. high) /. 2.0)
      }
    median
}
 
Js.log(median([4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]))
Js.log(median([4.1, 7.2, 1.7, 9.3, 4.4, 3.2]))
Output:
$ bsc median.res > median.bs.js
$ node median.bs.js
4.4
4.25

REXX

/*REXX program finds the  median  of a  vector  (and displays the  vector  and  median).*/
/*  ══════════vector════════════   ══show vector═══   ════════show result═══════════    */
    v=  1 9 2 4                ;   say "vector"  v;   say 'median──────►' median(v);   say
    v=  3 1 4 1 5 9 7 6        ;   say "vector"  v;   say 'median──────►' median(v);   say
    v= '3 4 1 -8.4 7.2 4 1 1.2';   say "vector"  v;   say 'median──────►' median(v);   say
    v=  -1.2345678e99  2.3e700 ;   say "vector"  v;   say 'median──────►' median(v);   say
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
eSORT:  procedure expose @. #;     parse arg $;     #= words($)   /*$:  is the  vector. */
                do g=1  for #;   @.g= word($, g);   end  /*g*/    /*convert list──►array*/
        h=#                                                       /*#:  number elements.*/
                do  while  h>1;             h= h % 2              /*cut entries by half.*/
                   do i=1  for #-h;         j= i;        k= h + i /*sort lower section. */
                      do  while @.k<@.j;    parse value  @.j @.k  with  @.k @.j  /*swap.*/
                      if h>=j  then leave;  j= j - h;    k= k - h /*diminish  J  and  K.*/
                      end   /*while @.k<@.j*/
                   end      /*i*/
                end         /*while h>1*/                         /*end of exchange sort*/
        return
/*──────────────────────────────────────────────────────────────────────────────────────*/
median: procedure; call eSORT arg(1);   m= # % 2    /*   %   is REXX's integer division.*/
        n= m + 1                                    /*N:     the next element after  M. */
        if # // 2  then return @.n                  /*[odd?]   // ◄───REXX's ÷ remainder*/
                        return (@.m + @.n) / 2      /*process an  even─element  vector. */
output:
vector: 1 9 2 4
median──────► 3

vector: 3 1 4 1 5 9 7 6
median──────► 4.5

vector: 3 4 1 -8.4 7.2 4 1 1.2
median──────► 2.1

vector: -1.2345678e99  2.3e700
median──────► 1.15000000E+700

Ring

aList = [5,4,2,3]
see "medium : " + median(aList) + nl

func median aray
     srtd = sort(aray)
     alen = len(srtd)
     if alen % 2 = 0 
        return (srtd[alen/2] + srtd[alen/2 + 1]) / 2.0
     else return srtd[ceil(alen/2)] ok

RPL

SORT
  DUP SIZE 1 + 2 /
  DUP2 FLOOR GET ROT ROT CEIL GET + 2 /
≫ 'MDIAN' STO

SORT became a standard RPL instruction in 1993, with the introduction of the HP-48G. For earlier RPL versions, users have to call the sorting program demonstrated here.

Ruby

def median(ary)
  return nil if ary.empty?
  mid, rem = ary.length.divmod(2)
  if rem == 0
    ary.sort[mid-1,2].inject(:+) / 2.0
  else
    ary.sort[mid]
  end
end

p median([])                        # => nil
p median([5,3,4])                   # => 4
p median([5,4,2,3])                 # => 3.5
p median([3,4,1,-8.4,7.2,4,1,1.2])  # => 2.1

Alternately:

def median(aray)
    srtd = aray.sort
    alen = srtd.length
    (srtd[(alen-1)/2] + srtd[alen/2]) / 2.0
end

Run BASIC

sqliteconnect #mem, ":memory:"
mem$ = "CREATE TABLE med (x float)"
#mem execute(mem$)

a$ ="4.1,5.6,7.2,1.7,9.3,4.4,3.2"	:gosub [median]
a$ ="4.1,7.2,1.7,9.3,4.4,3.2"		:gosub [median]
a$ ="4.1,4,1.2,6.235,7868.33"  		:gosub [median]
a$ ="1,5,3,2,4"       			:gosub [median]
a$ ="1,5,3,6,4,2"       		:gosub [median]
a$ ="4.4,2.3,-1.7,7.5,6.6,0.0,1.9,8.2,9.3,4.5"   :gosub [median]' 
end
[median]
#mem execute("DELETE FROM med")
for i = 1 to 100
	v$	= word$( a$, i, ",")
	if v$ = "" then exit for
	mem$	= "INSERT INTO med values(";v$;")"
	#mem execute(mem$)
next i
mem$ = "SELECT AVG(x) as median FROM (SELECT x FROM med 
ORDER BY x LIMIT 2 - (SELECT COUNT(*) FROM med) % 2  
OFFSET (SELECT (COUNT(*) - 1) / 2
FROM med))"

#mem	execute(mem$)
	#row 	= #mem #nextrow()
	median	= #row median()
print " Median :";median;chr$(9);" Values:";a$

RETURN

Output:

Median :4.4	 Values:4.1,5.6,7.2,1.7,9.3,4.4,3.2
 Median :4.25	 Values:4.1,7.2,1.7,9.3,4.4,3.2
 Median :4.1	 Values:4.1,4,1.2,6.235,7868.33
 Median :3.0	 Values:1,5,3,2,4
 Median :3.5	 Values:1,5,3,6,4,2
 Median :4.45	 Values:4.4,2.3,-1.7,7.5,6.6,0.0,1.9,8.2,9.3,4.5

Rust

Sorting, then obtaining the median element:

fn median(mut xs: Vec<f64>) -> f64 {
    // sort in ascending order, panic on f64::NaN
    xs.sort_by(|x,y| x.partial_cmp(y).unwrap() );
    let n = xs.len();
    if n % 2 == 0 {
        (xs[n/2] + xs[n/2 - 1]) / 2.0
    } else {
        xs[n/2]
    }
}

fn main() {
    let nums = vec![2.,3.,5.,0.,9.,82.,353.,32.,12.];
    println!("{:?}", median(nums))
}
Output:
9

Scala

Works with: Scala version 2.8

(See the Scala discussion on Mean for more information.)

def median[T](s: Seq[T])(implicit n: Fractional[T]) = {
  import n._
  val (lower, upper) = s.sortWith(_<_).splitAt(s.size / 2)
  if (s.size % 2 == 0) (lower.last + upper.head) / fromInt(2) else upper.head
}

This isn't really optimal. The methods splitAt and last are O(n/2) on many sequences, and then there's the lower bound imposed by the sort. Finally, we call size two times, and it can be O(n).

Scheme

Translation of: Python

Using Rosetta Code's bubble-sort function

(define (median l)
  (* (+ (list-ref (bubble-sort l >) (round (/ (- (length l) 1) 2)))
        (list-ref (bubble-sort l >) (round (/ (length l) 2)))) 0.5))

Using SRFI-95:

(define (median l)
  (* (+ (list-ref (sort l less?) (round (/ (- (length l) 1) 2)))
        (list-ref (sort l less?) (round (/ (length l) 2)))) 0.5))

Seed7

$ include "seed7_05.s7i";
  include "float.s7i";
 
const type: floatList is array float;
 
const func float: median (in floatList: floats) is func
  result
    var float: median is 0.0;
  local
    var floatList: sortedFloats is 0 times 0.0;
  begin
    sortedFloats := sort(floats);
    if odd(length(sortedFloats)) then
      median := sortedFloats[succ(length(sortedFloats)) div 2];
    else
      median := 0.5 * (sortedFloats[length(sortedFloats) div 2] +
                       sortedFloats[succ(length(sortedFloats) div 2)]);
    end if;
  end func;
 
const proc: main is func
  local
    const floatList: flist1 is [] (5.1, 2.6, 6.2, 8.8, 4.6, 4.1);
    const floatList: flist2 is [] (5.1, 2.6, 8.8, 4.6, 4.1);
  begin
    writeln("flist1 median is " <& median(flist1) digits 2 lpad 7); # 4.85
    writeln("flist2 median is " <& median(flist2) digits 2 lpad 7); # 4.60
  end func;

SenseTalk

SenseTalk has a built-in median function. This example also shows the implementation of a customMedian function that returns the same results.

put the median of [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]
put the median of [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2, 6.6]

put customMedian of [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2]
put customMedian of [4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2, 6.6]

to handle customMedian of list
	sort list
	if the number of items in list is an even number then
		set lowMid to the number of items in list divided by 2
		return (item lowMid of list + item lowMid+1 of list) / 2
	else
		return the middle item of list
	end if
end customMedian

Output:

4.4
5
4.4
5

Sidef

func median(arry) {
    var srtd = arry.sort;
    var alen = srtd.length;
    srtd[(alen-1)/2]+srtd[alen/2] / 2;
}

Slate

s@(Sequence traits) median
[
  s isEmpty
    ifTrue: [Nil]
    ifFalse:
      [| sorted |
       sorted: s sort.
       sorted length `cache isEven
         ifTrue: [(sorted middle + (sorted at: sorted indexMiddle - 1)) / 2]
         ifFalse: [sorted middle]]
].
inform: { 4.1 . 5.6 . 7.2 . 1.7 . 9.3 . 4.4 . 3.2 } median.
inform: { 4.1 . 7.2 . 1.7 . 9.3 . 4.4 . 3.2 } median.

Smalltalk

Works with: GNU Smalltalk
OrderedCollection extend [
    median [
      self size = 0
        ifFalse: [ |s l|
          l := self size.
          s := self asSortedCollection.
	  (l rem: 2) = 0 
	    ifTrue: [ ^ ((s at: (l//2 + 1)) + (s at: (l//2))) / 2 ]
	    ifFalse: [ ^ s at: (l//2 + 1) ]
	]
	ifTrue: [ ^nil ]
    ]
].
{ 4.1 . 5.6 . 7.2 . 1.7 . 9.3 . 4.4 . 3.2 } asOrderedCollection
   median displayNl.
{ 4.1 . 7.2 . 1.7 . 9.3 . 4.4 . 3.2 } asOrderedCollection
   median displayNl.

Stata

Use summarize to compute the median of a variable (as well as other basic statistics).

set obs 100000
gen x=rbeta(0.2,1.3)
quietly summarize x, detail
display r(p50)

Here is a straightforward implementation using sort.

program calcmedian, rclass sortpreserve
sort `1'
if mod(_N,2)==0 {
	return scalar p50=(`1'[_N/2]+`1'[_N/2+1])/2
}
else {
	return scalar p50=`1'[(_N-1)/2]
}
end

calcmedian x
display r(p50)

Swift

A full implementation

    // Utility to aid easy type conversion
extension Double {
	init(withNum v: any Numeric) {
		switch v {
		case let ii as any BinaryInteger: self.init(ii)
		case let ff as any BinaryFloatingPoint: self.init(ff)
		default: self.init()
		}
	}
}

extension Array where Element: Numeric & Comparable {
        // Helper func for random element in range
	func randomElement(within: Range<Int>) -> Element {
		return self[.random(in: within)]
	}

	mutating func median() -> Double? {
		switch self.count {
		case 0: return nil
		case 1: return Double(withNum: self[0])
		case 2: return self.reduce(0, {sum,this in sum + Double(withNum: this)/2.0})
		default: break
		}
		let pTarget: Int = self.count / 2 + 1
		let resultSetLen: Int = self.count.isMultiple(of: 2) ? 2 : 1
		func divideAndConquer(bottom: Int, top: Int, goal: Int) -> Int {
			var (lower,upper) = (bottom,top)
			while true {
				let splitVal = self.randomElement(within: lower..<upper)
				let partitionIndex =  self.partition(subrange: lower..<upper, by: {$0 > splitVal})
				switch partitionIndex {
				case goal: return partitionIndex
				case ..<goal: lower = partitionIndex
				default: upper = partitionIndex
				}
			}
		}
			// Split just above the 'median point'
		var pIndex = divideAndConquer(bottom: 0, top: self.count, goal: pTarget)
			// Shove the highest 'low' values into the result slice
		pIndex = divideAndConquer(bottom: 0, top: pIndex, goal: pIndex - resultSetLen)
			// Average the contents of the result slice
		return self[pIndex..<pIndex + resultSetLen]
			.reduce(0.0, {sum,this in sum + Double(withNum: this)/Double(withNum: resultSetLen)})
	}
}

Usage:

var c: [Double] = (0...100).map {_ in Double.random(in: 0...100)} 
print(c.median())

Tcl

proc median args {
    set list [lsort -real $args]
    set len [llength $list]
    # Odd number of elements
    if {$len & 1} {
        return [lindex $list [expr {($len-1)/2}]]
    }
    # Even number of elements
    set idx2 [expr {$len/2}]
    set idx1 [expr {$idx2-1}]
    return [expr {
        ([lindex $list $idx1] + [lindex $list $idx2])/2.0
    }]
}

puts [median 3.0 4.0 1.0 -8.4 7.2 4.0 1.0 1.2]; # --> 2.1

TI-83 BASIC

Using the built-in function:

median({1.1, 2.5, 0.3241})

TI-89 BASIC

median({3, 4, 1, -8.4, 7.2, 4, 1, 1})

Ursala

the simple way (sort first and then look in the middle)

#import std
#import flo

median = fleq-<; @K30K31X eql?\~&rh div\2.+ plus@lzPrhPX

test program, once with an odd length and once with an even length vector

#cast %eW

examples =

median~~ (
   <9.3,-2.0,4.0,7.3,8.1,4.1,-6.3,4.2,-1.0,-8.4>,
   <8.3,-3.6,5.7,2.3,9.3,5.4,-2.3,6.3,9.9>)

output:

(4.050000e+00,5.700000e+00)

Vala

Requires --pkg posix -X -lm compilation flags in order to use POSIX qsort, and to have access to math library.

int compare_numbers(void* a_ref, void* b_ref) {
    double a = *(double*) a_ref;
    double b = *(double*) b_ref;
    return a > b ? 1 : a < b ? -1 : 0;
}

double median(double[] elements) {
    double[] clone = elements;
    Posix.qsort(clone, clone.length, sizeof(double), compare_numbers);
    double middle = clone.length / 2.0;
    int first = (int) Math.floor(middle);
    int second = (int) Math.ceil(middle);
    return (clone[first] + clone[second]) / 2;
}
void main() {
    double[] array1 = {2, 4, 6, 1, 7, 3, 5};
    double[] array2 = {2, 4, 6, 1, 7, 3, 5, 8};
    print(@"$(median(array1)) $(median(array2))\n");
}

VBA

Translation of: Phix

Uses quick select.

Private Function medianq(s As Variant) As Double
    Dim res As Double, tmp As Integer
    Dim l As Integer, k As Integer
    res = 0
    l = UBound(s): k = WorksheetFunction.Floor_Precise((l + 1) / 2, 1)
        If l Then
            res = quick_select(s, k)
            If l Mod 2 = 0 Then
                tmp = quick_select(s, k + 1)
                res = (res + tmp) / 2
            End If
        End If
    medianq = res
End Function
Public Sub main2()
    s = [{4, 2, 3, 5, 1, 6}]
    Debug.Print medianq(s)
End Sub
Output:
 3,5 

Vedit macro language

This is a simple implementation for positive integers using sorting. The data is stored in current edit buffer in ascii representation. The values must be right justified.

The result is returned in text register @10. In case of even number of items, the lower middle value is returned.

Sort(0, File_Size, NOCOLLATE+NORESTORE)
EOF Goto_Line(Cur_Line/2)
Reg_Copy(10, 1)

V (Vlang)

fn main() {
    println(median([3, 1, 4, 1]))    // prints 2
    println(median([3, 1, 4, 1, 5])) // prints 3
}
 
fn median(aa []int) int {
    mut a := aa.clone()
    a.sort()
    half := a.len / 2
    mut m := a[half]
    if a.len%2 == 0 {
        m = (m + a[half-1]) / 2
    }
    return m
}
Output:
2
3

If you use math.stats module the list parameter must be sorted

import math.stats
fn main() {
    println(stats.median<int>([1, 1, 3, 4]))    // prints 2
    println(stats.median<int>([1, 1, 3, 4, 5])) // prints 3
}

Wortel

@let {
  ; iterative
  med1 &l @let {a @sort l s #a i @/s 2 ?{%%s 2 ~/ 2 +`-i 1 a `i a `i a}}

  ; tacit
  med2 ^(\~/2 @sum @(^(\&![#~f #~c] \~/2 \~-1 #) @` @id) @sort)

  [[
    !med1 [4 2 5 2 1]
    !med1 [4 5 2 1]
    !med2 [4 2 5 2 1]
    !med2 [4 5 2 1]
  ]]
}

Returns:

[2 3 2 3]

Wren

Library: Wren-sort
Library: Wren-math
Library: Wren-queue
import "./sort" for Sort, Find
import "./math" for Nums
import "./queue" for PriorityQueue

var lists = [
    [5, 3, 4],
    [3, 4, 1, -8.4, 7.2, 4, 1, 1.2]
]

for (l in lists) {
    // sort and then find median
    var l2 = Sort.merge(l)
    System.print(Nums.median(l2))

    // using a priority queue
    var pq = PriorityQueue.new()
    for (e in l) pq.push(e, -e)
    var c = pq.count
    var v = pq.values
    var m = (c % 2 == 1) ? v[(c/2).floor] : (v[c/2] + v[c/2-1])/2
    System.print(m)

    // using quickselect
    if (c % 2 == 1) {
        System.print(Find.quick(l, (c/2).floor))
    } else {
        var m1 = Find.quick(l, c/2-1)
        var m2 = Find.quick(l, c/2)
        System.print((m1 + m2)/2)
    }
    System.print()
}
Output:
4
4
4

2.1
2.1
2.1

XPL0

func real Median(Size, Array);  \Return median value of Array
int  Size;  real Array;
int  I, J, MinJ;
real Temp;
[for I:= 0 to Size/2 do         \partial selection sort
    [MinJ:= I;
    for J:= I+1 to Size-1 do
        if Array(J) < Array(MinJ) then MinJ:= J;
    Temp:= Array(I);  Array(I):= Array(MinJ);  Array(MinJ):= Temp;
    ];
if rem(Size/2) = 1 then return Array(Size/2)
else return (Array(Size/2-1) + Array(Size/2)) / 2.;
];

[RlOut(0, Median(3, [5.0, 3.0, 4.0]));  CrLf(0);
 RlOut(0, Median(8, [3.0, 4.0, 1.0, -8.4, 7.2, 4.0, 1.0, 1.2]));  CrLf(0);
]
Output:
    4.00000
    2.10000

Yabasic

Translation of: Lua
sub floor(x)
    return int(x + .05)
end sub

sub ceil(x)
    if x > int(x) x = x + 1 
    return x
end sub

SUB ASort$(matriz$())
    local last, gap, first, tempi$, tempj$, i, j

    last = arraysize(matriz$(), 1)

    gap = floor(last / 10) + 1
    while(TRUE)
	first = gap + 1
	for i = first to last
	    tempi$ = matriz$(i)
	    j = i - gap
	    while(TRUE)
	        tempj$ = matriz$(j)
	 	if (tempi$ >= tempj$) then
	   	    j = j + gap
	   	    break
	 	end if
	 	matriz$(j+gap) = tempj$
	 	if j <= gap then
	   	    break
	 	end if
	 	j = j - gap
	    wend
	    matriz$(j) = tempi$
        next i
	if gap = 1 then
	    return
	else
	    gap = floor(gap / 3.5) + 1
	end if
    wend
END SUB


sub median(numlist$)
    local numlist$(1), n
    
    n = token(numlist$, numlist$(), ", ")
    
    ASort$(numlist$())
    
    if mod(n, 2) = 0 then return (val(numlist$(n / 2)) + val(numlist$(n / 2 + 1))) / 2 end if
    return val(numlist$(ceil(n / 2)))
end sub

print median("4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2")    // 4.4
print median("4.1, 7.2, 1.7, 9.3, 4.4, 3.2")         // 4.25

zkl

Using the Quickselect algorithm#zkl for O(n) time:

var quickSelect=Import("quickSelect").qselect;

fcn median(xs){
   n:=xs.len();
   if (n.isOdd) return(quickSelect(xs,n/2));
   ( quickSelect(xs,n/2-1) + quickSelect(xs,n/2) )/2;
}
median(T( 5.1, 2.6, 6.2, 8.8, 4.6, 4.1 )); //-->4.85
median(T( 5.1, 2.6, 8.8, 4.6, 4.1 ));      //-->4.6

Zoea

program: median
  case: 1
    input: [4,5,6,8,9]
    output: 6
  case: 2
    input: [2,5,6]
    output: 5
  case: 3
    input: [2,5,6,8]
    output: 5.5

Zoea Visual

Median

zonnon

module Averages;

type
	Vector = array {math} * of real;

procedure Partition(var a: Vector; left, right: integer): integer;
var
	pValue,aux: real;
	store,i,pivot: integer;
begin
	pivot := right;
	pValue := a[pivot];
	aux := a[right];a[right] := a[pivot];a[pivot] := aux; (* a[pivot] <-> a[right] *)
	store := left;
	for i := left to right -1 do 
		if a[i] <= pValue then
			aux := a[store];a[store] := a[i];a[i]:=aux;
			inc(store)
		end
	end;
	aux := a[right];a[right] := a[store]; a[store] := aux;
	return store
end Partition;

(* QuickSelect algorithm *)
procedure Select(a: Vector; left,right,k: integer;var r: real);
var
	pIndex, pDist : integer;
begin
	if left = right then r := a[left]; return end;
	pIndex := Partition(a,left,right);
	pDist := pIndex - left + 1;
	if pDist = k then
		r := a[pIndex];return
	elsif k < pDist then
		Select(a,left, pIndex - 1, k, r)
	else
		Select(a,pIndex + 1, right, k - pDist, r)
	end
end Select;

procedure Median(a: Vector): real;
var
	idx: integer;
	r1,r2 : real;
begin
	idx := len(a) div 2 + 1;
	r1 := 0.0;r2 := 0.0;
	Select(a,0,len(a) - 1,idx,r1);
	if odd(len(a)) then return r1 end;
	Select(a,0,len(a) - 1,idx - 1,r2);
	return (r1 + r2) / 2;
end Median;

var
	ary: Vector;
	r: real;

begin
	ary := new Vector(3);
	ary := [5.0,3.0,4.0];
	writeln(Median(ary):10:2);
	ary := new Vector(4);
	ary := [5.0,4.0,2.0,3.0];
	writeln(Median(ary):10:2);
	ary := new Vector(8);
	ary := [3.0,4.0,1.0,-8.4,7.2,4.0,1.0,1.2];
	writeln(Median(ary):10:2)
end Averages.
        4
       3,5
       2,1