Averages/Median: Difference between revisions
→{{header|C sharp|C#}}
Alextretyak (talk | contribs) m (→{{header|11l}}) |
RandomTask (talk | contribs) |
||
(76 intermediate revisions by 41 users not shown) | |||
Line 1:
[[Category:Sorting]]
[[Category:E examples needing attention]]
{{task|Probability and statistics}}
;Task
Write a program to find the [[wp:Median|median]] value of a vector of floating-point numbers.
Line 19 ⟶ 21:
=={{header|11l}}==
{{trans|Python}}
<
V srtd = sorted(aray)
V alen = srtd.len
Line 25 ⟶ 27:
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]))</
{{out}}
<pre>
4.4
4.25
</pre>
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }}
<syntaxhighlight lang AArch64 Assembly>
/* 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"
</syntaxhighlight>
{{Out}}
<pre>
Result : +4,4
Result : +4,25
</pre>
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
{{libheader|Action! Real Math}}
<syntaxhighlight lang="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</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Averages_Median.png Screenshot from Atari 8-bit computer]
<pre>
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
</pre>
=={{header|Ada}}==
<
procedure FindMedian is
Line 63 ⟶ 741:
Ada.Float_Text_IO.Put( median_val );
Ada.Text_IO.New_line;
end FindMedian;</
=={{header|ALGOL 68}}==
{{trans|C}}<
# Return the k-th smallest item in array x of length len #
Line 129 ⟶ 808:
"<: ", whole (less,0), new line,
">: ", whole (more, 0), new line,
"=: ", whole (eq, 0), new line))</
Sample output:
<pre>length: 97738
Line 136 ⟶ 815:
>: 48870
=: 0
</pre>
=={{header|Amazing Hopper}}==
{{trans|BaCon}}<syntaxhighlight lang="c">
#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
</syntaxhighlight>
{{out}}
<pre>
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
</pre>
=={{header|AntLang}}==
AntLang has a built-in median function.
<syntaxhighlight lang
=={{header|APL}}==
<
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: <syntaxhighlight lang
If you prefer an index origin of 1, use this code instead:
<syntaxhighlight lang="apl">
⎕IO←1
median←{v←⍵[⍋⍵] ⋄ 0.5×v[⌈0.5×⍴v]+v[⌊1+0.5×⍴v]}
</syntaxhighlight>
This code was tested with ngn/apl and Dyalog 12.1. You can try this function online with [http://ngn.github.io/apl/web/index.html#code=median%u2190%7Bv%u2190%u2375%5B%u234B%u2375%5D%u22C4.5%D7v%5B%u2308%AF1+.5%D7%u2374v%5D+v%5B%u230A.5%D7%u2374v%5D%7D ngn/apl]. Note that ngn/apl currently only supports index origin 0. Examples:
Line 187 ⟶ 907:
median 'HELLO'
DOMAIN ERROR</pre>
=={{header|AppleScript}}==
===By iteration===
<
set med to medi(alist)
Line 196 ⟶ 916:
set temp to {}
set lcount to count
if lcount is equal to 2 then
return ((item
else if lcount is less than 2 then
return item 1 of alist
Line 233 ⟶ 953:
return max
end findmax</
{{output}}
<syntaxhighlight lang="applescript">4.5</syntaxhighlight>
===Composing functionally===
Line 239 ⟶ 962:
{{Trans|JavaScript}}
{{Trans|Haskell}}
<
-- median :: [Num] -> Num
Line 344 ⟶ 1,067:
missing value
end if
end uncons</
{{Out}}
<
----
===Quickselect===
<syntaxhighlight lang="applescript">-- 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))}</syntaxhighlight>
{{output}}
<pre>{|numbers|:{71.6, 44.8, 45.8, 28.6, 96.8, 98.4, 42.4, 97.8}, median:58.7}</pre>
===Partial heap sort===
<syntaxhighlight lang="applescript">-- 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))}
</syntaxhighlight>
{{output}}
<syntaxhighlight lang="applescript">{|numbers|:{28.0, 75.6, 21.4, 51.8, 79.6, 25.0, 95.4, 31.2}, median:41.5}</syntaxhighlight>
=={{header|Applesoft BASIC}}==
<
110 K = INT(L/2) : GOSUB 150
120 R = X(K)
Line 373 ⟶ 1,243:
300 REMSWAP
310 H = X(P1):X(P1) = X(P2)
320 X(P2) = H: RETURN</
L = 11 : GOSUB 100MEDIAN
? R</
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}}
<syntaxhighlight lang ARM Assembly>
/* 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"
</syntaxhighlight>
{{Out}}
<pre>
Result : +4,40000009E0
Result : +4,25E0
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">arr: [1 2 3 4 5 6 7]
arr2: [1 2 3 4 5 6]
print median arr
print median arr2</syntaxhighlight>
{{out}}
<pre>4
3.5</pre>
=={{header|AutoHotkey}}==
Takes the lower of the middle two if length is even
<
MsgBox % median(seq, "`,") ; 4.1
Line 387 ⟶ 1,775:
median := Floor(seq0 / 2)
Return seq%median%
}</
=={{header|AWK}}==
Line 393 ⟶ 1,781:
AWK arrays can be passed as parameters, but not returned, so they are usually global.
<
BEGIN {
Line 439 ⟶ 1,827:
print ""
}
</syntaxhighlight>
Example output:
Line 447 ⟶ 1,835:
=={{header|BaCon}}==
<
DECLARE b[] = { 4.1, 7.2, 1.7, 9.3, 4.4, 3.2 } TYPE FLOATING
Line 458 ⟶ 1,846:
SORT b
PRINT "Median of b: ", Median(b)</
{{out}}
<pre>
Line 476 ⟶ 1,864:
Note that in order to truly work with the Windows versions of PowerBASIC, the module-level code must be contained inside <code>FUNCTION PBMAIN</code>. Similarly, in order to work under Visual Basic, the same module-level code must be contained with <code>Sub Main</code>.
<
DIM vec1(10) AS SINGLE, vec2(11) AS SINGLE, n AS INTEGER
Line 505 ⟶ 1,893:
median = (v(INT((ub + lb) / 2)) + v(INT((ub + lb) / 2) + 1)) / 2
END IF
END FUNCTION</
See also: [[#BBC BASIC|BBC BASIC]], [[#Liberty BASIC|Liberty BASIC]], [[#PureBasic|PureBasic]], [[#TI-83 BASIC|TI-83 BASIC]], [[#TI-89 BASIC|TI-89 BASIC]].
Line 511 ⟶ 1,899:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<
Sort% = FN_sortinit(0,0)
Line 527 ⟶ 1,915:
CALL Sort%, a(0)
= (a(C% DIV 2) + a((C%-1) DIV 2)) / 2
</syntaxhighlight>
Output:
<pre>Median of a() is 4.4
Median of b() is 4.25</pre>
=={{header|BQN}}==
A tacit definition from [https://mlochbaum.github.io/bqncrate/ BQNcrate] which sorts and takes the middle elements of the array.
<pre>Median ← (+´÷≠)∧⊏˜2⌊∘÷˜¯1‿0+≠
Median 5.961475‿2.025856‿7.262835‿1.814272‿2.281911‿4.854716</pre>
<pre>3.5683135</pre>
=={{header|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.
<
= begin decimals end int list
, med med1 med2 num number
. ( convertToRational
& (
& (ufp..export)$(Q.V)
& 0:?list
& whl
' (
&
& (!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))
);</syntaxhighlight>
Output:
<pre>4.0999999999999996E+00
4.4500000000000002E+00
3.0000000000000000E+00
3.5000000000000000E+00</pre>
=={{header|C}}==
<
#include <stdlib.h>
Line 607 ⟶ 2,017:
printf("flist2 median is %7.2f\n", median(&flist2)); /* 4.60 */
return 0;
}</
===Quickselect algorithm===
Average O(n) time:
<
#include <stdlib.h>
#include <time.h>
Line 689 ⟶ 2,099:
return 0;
}
</syntaxhighlight>
Output:
<
median: 0.000473
<: 496010
>: 496010
=: 1</
=={{header|C sharp|C#}}==
{{works with|C sharp|C#|10+}}
<syntaxhighlight lang="csharp">
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
</syntaxhighlight>
{{output}}
<pre>
[1, 5, 3, 6, 4, 2]: 3.5
[1, 5, 3, 6, 4, 2, 7]: 4
[5]: 5
</pre>
=={{header|C++}}==
This function runs in linear time on average.
<
// inputs must be random-access iterators of doubles
Line 731 ⟶ 2,166:
return 0;
}</
===Order Statistic Tree===
Uses a GNU C++ policy-based data structure to compute median in O(log n) time.
{{libheader|gnu_pbds}}
<syntaxhighlight lang="cpp">#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()
{
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
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
}
</syntaxhighlight>
=={{header|Clojure}}==
Simple:
<
(let [ns (sort ns)
cnt (count ns)
Line 776 ⟶ 2,220:
(if (odd? cnt)
(nth ns mid)
(/ (+ (nth ns mid) (nth ns (dec mid))) 2))))</
=={{header|COBOL}}==
Intrinsic function:
<
=={{header|Common Lisp}}==
Line 786 ⟶ 2,230:
The recursive partitioning solution, without the median of medians optimization.
<
"Select nth element in list, ordered by predicate, modifying list."
(do ((pivot (pop list))
Line 808 ⟶ 2,252:
(defun median (list predicate)
(select-nth (floor (length list) 2) list predicate))</
=={{header|Craft Basic}}==
<syntaxhighlight lang="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</syntaxhighlight>
{{out| Output}}
<pre>
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
</pre>
=={{header|Crystal}}==
<syntaxhighlight lang="ruby">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
</syntaxhighlight>
{{out}}
<pre>
4.4
4.7
5.0
</pre>
=={{header|D}}==
<
T median(T)(T[] nums) pure nothrow {
Line 827 ⟶ 2,475:
auto a2 = [5.1, 2.6, 8.8, 4.6, 4.1];
writeln("Odd median: ", a2.median);
}</
{{out}}
<pre>Even median: 4.85
Line 833 ⟶ 2,481:
=={{header|Delphi}}==
<
{$APPTYPE CONSOLE}
Line 855 ⟶ 2,503:
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.</
=={{header|E}}==
TODO: Use the selection algorithm, whatever that is
<syntaxhighlight lang="e">def median(list) {
def sorted := list.sort()
def count := sorted.size()
Line 871 ⟶ 2,518:
return (sorted[mid1] + sorted[mid2]) / 2
}
}</
<
# value: 2
? median([1,9,2,4])
# value: 3.0</
=={{header|EasyLang}}==
<syntaxhighlight lang="text">
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
</syntaxhighlight>
<pre>
4.40
4.25
</pre>
=={{header|EchoLisp}}==
<
(define (median L) ;; O(n log(n))
(set! L (vector-sort! < (list->vector L)))
Line 896 ⟶ 2,593:
(median (iota 10001))
→ 5000
</syntaxhighlight>
=={{header|Elena}}==
ELENA
<
import system'math
import extensions
extension op
{
var
var
if (
{
}
{
var middleIndex := len /
^ (sorted[middleIndex - 1] + sorted[middleIndex]) / 2
}
else
{
^ sorted[middleIndex]
}
}
}
}
public program()
{
var a1 :=
var a2 :=
console
console
console
}</syntaxhighlight>
{{out}}
<pre>
Line 940 ⟶ 2,645:
=={{header|Elixir}}==
{{trans|Erlang}}
<
def median([]), do: nil
def median(list) do
Line 955 ⟶ 2,660:
Enum.each(1..6, fn i ->
(for _ <- 1..i, do: :rand.uniform(6)) |> median.()
end)</
{{out}}
Line 966 ⟶ 2,671:
[3, 2, 6, 3, 2] => 3
[6, 4, 2, 3, 1, 3] => 3.0
</pre>
=={{header|EMal}}==
===Sort===
<syntaxhighlight lang="emal">
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))
</syntaxhighlight>
{{out}}
<pre>
4.7
</pre>
===Quickselect===
<syntaxhighlight lang="emal">
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))
</syntaxhighlight>
{{out}}
<pre>
4.7
</pre>
=={{header|Erlang}}==
<
-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) ->
Line 978 ⟶ 2,752:
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.
</syntaxhighlight>
=={{header|ERRE}}==
<syntaxhighlight lang="text">
PROGRAM MEDIAN
Line 1,018 ⟶ 2,831:
PRINT(R)
END PROGRAM
</syntaxhighlight>
Ouput is 5.95
Line 1,027 ⟶ 2,840:
v. Moreover it can search for the p median, not only the p=0.5 median.
<syntaxhighlight lang="euler math toolbox">
>type median
function median (x, v: none, p)
Line 1,078 ⟶ 2,891:
>0.2*10+0.8*1
2.8
</syntaxhighlight>
=={{header|Euphoria}}==
<
atom min,k
-- Selection sort of half+1
Line 1,105 ⟶ 2,918:
end function
? median({ 4.4, 2.3, -1.7, 7.5, 6.6, 0.0, 1.9, 8.2, 9.3, 4.5 })</
Output:
Line 1,114 ⟶ 2,927:
Assuming the values are entered in the A column, type into any cell which will not be part of the list :
<
=MEDIAN(A1:A10)
</syntaxhighlight>
Assuming 10 values will be entered, alternatively, you can just type
<
=MEDIAN(
</syntaxhighlight>
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
<syntaxhighlight lang="text">
23 11,5
21
Line 1,138 ⟶ 2,951:
9
0
</syntaxhighlight>
=={{header|F Sharp|F#}}==
Median of Medians algorithm implementation
<
let rec splitToFives list =
match list with
Line 1,187 ⟶ 3,000:
let z' = [1.;5.;2.;8.;7.]
start z'
</syntaxhighlight>
=={{header|Factor}}==
The quicksort-style solution, with random pivoting. Takes the lesser of the two medians for even sequences.
<
IN: median
Line 1,217 ⟶ 3,030:
: median ( seq -- median )
dup length 1 - 2 / floor nth-in-order ;</
Usage:
<
5
( scratchpad ) 10 iota median .
4</
=={{header|Forth}}==
This uses the O(n) algorithm derived from [[quicksort]].
<
: cell- -cell + ;
Line 1,256 ⟶ 3,069:
: median ( array len -- m )
1- cells over + 2dup mid to midpoint
select midpoint @ ;</
<
test 4 median . \ 2
test 5 median . \ 3</
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<
real :: a(7) = (/ 4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2 /), &
Line 1,307 ⟶ 3,120:
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, <
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).
=={{header|FreeBASIC}}==
<
Sub quicksort(a() As Double, first As Integer, last As Integer)
Line 1,360 ⟶ 3,173:
Print
Print "Press any key to quit"
Sleep</
{{out}}
Line 1,367 ⟶ 3,180:
Median for first 9 elements : 4.4
</pre>
=={{header|FutureBasic}}==
FB has native averaging functions.
<syntaxhighlight lang="futurebasic">
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
</syntaxhighlight>
{{output}}
<pre>
2
3
3.5683135
4.4
890.45
</pre>
=={{header|GAP}}==
<
local n, w;
w := SortedList(v);
Line 1,382 ⟶ 3,225:
# 44
Median(b);
# 85/2</
=={{header|Go}}==
===Sort===
Go built-in sort. O(n log n).
<
import (
Line 1,406 ⟶ 3,250:
}
return m
}</
===Partial selection sort===
Line 1,412 ⟶ 3,256:
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().
<
import "fmt"
Line 1,442 ⟶ 3,286:
}
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.
<
import (
Line 1,496 ⟶ 3,340:
}
return a[0]
}</
=={{header|Groovy}}==
Solution (brute force sorting, with arithmetic averaging of dual midpoints (even sizes)):
<
def s = col as SortedSet
if (s == null) return null
Line 1,508 ⟶ 3,352:
def l = s.collect { it }
n%2 == 1 ? l[m] : (l[m] + l[m-1])/2
}</
Test:
<
def sz = a.size()
Line 1,517 ⟶ 3,361:
println """${median(a[0..<(sz-it)])} == median(${a[0..<(sz-it)]})
${median(a[it..<sz])} == median(${a[it..<sz]})"""
}</
Output:
Line 1,546 ⟶ 3,390:
This uses a quick select algorithm and runs in expected O(n) time.
<
nth :: Ord t => [t] -> Int -> t
Line 1,571 ⟶ 3,415:
[[], [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</
{{Out}}
<pre>(not defined)
Line 1,581 ⟶ 3,425:
Or {{libheader|hstats}}
<
3.0</
=={{header|HicEst}}==
If the input has an even number of elements, median is the mean of the middle two values:
<
vec = RAN(1)
Line 1,595 ⟶ 3,439:
ELSE
median = ( vec(n/2) + vec(n/2 + 1) ) / 2
ENDIF</
=={{header|Icon}} and {{header|Unicon}}==
A quick and dirty solution:
<syntaxhighlight lang="text">procedure main(args)
write(median(args))
end
Line 1,608 ⟶ 3,452:
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:
Line 1,619 ⟶ 3,463:
=={{header|J}}==
The verb <code>median</code> is available from the <code>stats/base</code> addon and returns the mean of the two middle values for an even number of elements:
<
median 1 9 2 4
3</
The definition given in the addon script is:
<
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 1 9 2 4
2 4</
=={{header|Java}}==
Line 1,635 ⟶ 3,479:
Sorting:
<syntaxhighlight lang="java">
/* 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;
};
}
</syntaxhighlight>
{{works with|Java|1.5+}}
Using priority queue (which sorts under the hood):
<
PriorityQueue<Double> pq = new PriorityQueue<Double>(list);
int n = list.size();
Line 1,653 ⟶ 3,510:
else
return (pq.poll() + pq.poll()) / 2.0;
}</
{{works with|Java|1.8+}}
This version operates on objects rather than primitives and uses abstractions to operate on all of the standard numerics.
<syntaxhighlight lang="java8">
@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); }
}
</syntaxhighlight>
=={{header|JavaScript}}==
===ES5===
<
if (ary.length == 0)
return null;
Line 1,672 ⟶ 3,586:
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===
Line 1,679 ⟶ 3,593:
{{Trans|Haskell}}
<
'use strict';
Line 1,730 ⟶ 3,644:
[3, 4, 1, -8.4, 7.2, 4, 1, 1.2]
].map(median);
})();</
{{Out}}
<syntaxhighlight lang="javascript">[
null,
4,
3.5,
2.1
]</
=={{header|jq}}==
<
length as $length
| sort as $s
Line 1,750 ⟶ 3,664:
else $s[$l2]
end
end ;</
[4.1, 7.2, 1.7, 9.3, 4.4, 3.2]</
4.4
4.25</
=={{header|Julia}}==
Julia has a built-in median() function
<syntaxhighlight lang
function median2(n)
s = sort(n)
Line 1,771 ⟶ 3,685:
b = [4.1, 7.2, 1.7, 9.3, 4.4, 3.2]
@show a b median2(a) median(a) median2(b) median(b) </
{{out}}
Line 1,784 ⟶ 3,698:
=={{header|K}}==
<syntaxhighlight lang="k">
med:{a:x@<x; i:(#a)%2; :[(#a)!2; a@i; {(+/x)%#x} a@i,i-1]}
v:10*6 _draw 0
Line 1,793 ⟶ 3,707:
med[1_ v]
2.281911
</syntaxhighlight>
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:
<syntaxhighlight lang="k">
med:{a:x@<x; i:_(#a)%2
$[2!#a; a@i; |a@i,i-1]}
med[v]
2.2819 4.8547
</syntaxhighlight>
=={{header|Kotlin}}==
{{works with|Kotlin|1.0+}}
<
fun main(args: Array<String>) {
Line 1,811 ⟶ 3,725:
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
}</
=={{header|Lambdatalk}}==
{{trans|11l}}
<syntaxhighlight lang="scheme">
{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
</syntaxhighlight>
=={{header|Lasso}}==
Line 1,818 ⟶ 3,750:
Lasso's built in function is "median( value_1, value_2, value_3 )"
<
#a->sort
Line 1,832 ⟶ 3,764:
median_ext(array(3,2,7,6)) // 4.5
median_ext(array(3,2,9,7,6)) // 6</
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
dim a( 100), b( 100) ' assumes we will not have vectors of more terms...
Line 1,880 ⟶ 3,812:
if middle <>intmiddle then median= a( 1 +intmiddle) else median =( a( intmiddle) +a( intmiddle +1)) /2
end function
</syntaxhighlight>
<pre>
4.1 5.6 7.2 1.7 9.3 4.4 3.2
Line 1,902 ⟶ 3,834:
=={{header|Lingo}}==
<
-- numlist = numlist.duplicate() -- if input list should not be altered
numlist.sort()
Line 1,910 ⟶ 3,842:
return (numlist[numlist.count/2]+numlist[numlist.count/2+1])/2.0
end if
end</
=={{header|LiveCode}}==
LC has median as a built-in function
<
returns 4.4, 4.25</
To make our own, we need own own floor function first
<
if n < 0 then
return (trunc(n) - 1)
Line 1,942 ⟶ 3,874:
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</
=={{header|LSL}}==
<
integer MAX_VALUE = 100;
default {
Line 1,966 ⟶ 3,898:
llOwnerSay(" Sum Squares: "+(string)llListStatistics(LIST_STAT_SUM_SQUARES, lst));
}
}</
Output:
<pre>
Line 1,983 ⟶ 3,915:
=={{header|Lua}}==
<
if type(numlist) ~= 'table' then return numlist end
table.sort(numlist)
Line 1,991 ⟶ 3,923:
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}))</
=={{header|Maple}}==
=== Builtin ===
This works for numeric lists or arrays, and is designed for large data sets.
<syntaxhighlight lang="maple">
> Statistics:-Median( [ 1, 5, 3, 2, 4 ] );
3.
Line 2,002 ⟶ 3,934:
> Statistics:-Median( [ 1, 5, 3, 6, 2, 4 ] );
3.50000000000000
</syntaxhighlight>
=== 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.
<syntaxhighlight lang="maple">
median1 := proc()
local L := sort( [ args ] );
( L[ iquo( 1 + nargs, 2 ) ] + L[ 1 + iquo( nargs, 2 ) ] ) / 2
end proc:
</syntaxhighlight>
For example:
<syntaxhighlight lang="maple">
> median1( 1, 5, 3, 2, 4 ); # 3
3
Line 2,018 ⟶ 3,950:
> median1( 1, 5, 3, 6, 4, 2 ); # 7/2
7/2
</syntaxhighlight>
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Built-in function:
<
Median[{1, 5, 3, 6, 4, 2}]</
{{out}}
<pre>3
7/2</pre>
Custom function:
<
If[Mod[L,2]==0,
(t[[L/2]]+t[[L/2+1]])/2
Line 2,034 ⟶ 3,966:
t[[(L+1)/2]]
]
]</
Example of custom function:
<
mymedian[{1, 5, 3, 6, 4, 2}]</
{{out}}
<pre>3
Line 2,044 ⟶ 3,976:
=={{header|MATLAB}}==
If the input has an even number of elements, function returns the mean of the middle two values:
<
medianValue = median(setOfValues);
end</
=={{header|Maxima}}==
<
median([41, 56, 72, 17, 93, 44, 32]); /* 44 */
median([41, 72, 17, 93, 44, 32]); /* 85/2 */</
=={{header|min}}==
<syntaxhighlight lang="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!</syntaxhighlight>
{{out}}
<pre>4.4
4.25</pre>
=={{header|MiniScript}}==
<syntaxhighlight lang="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</syntaxhighlight>
{{out}}
<pre>44
42.5</pre>
=={{header|MUMPS}}==
<
;X is assumed to be a list of numbers separated by "^"
;I is a loop index
Line 2,067 ⟶ 4,023:
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)
</syntaxhighlight>
<pre>USER>W $$MEDIAN^ROSETTA("-1.3^2.43^3.14^17^2E-3")
3.14
Line 2,076 ⟶ 4,032:
USER>W $$MEDIAN^ROSETTA
No data</pre>
=={{header|Nanoquery}}==
{{trans|Python}}
<syntaxhighlight lang="nanoquery">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)</syntaxhighlight>
=={{header|NetRexx}}==
{{trans|Java}}
<
options replace format comments java crossref symbols nobinary
Line 2,143 ⟶ 4,114:
if i > j then return +1
else return 0
</syntaxhighlight>
'''Output:'''
<pre>
Line 2,167 ⟶ 4,138:
=={{header|NewLISP}}==
<
; oofoe 2012-01-25
Line 2,189 ⟶ 4,160:
(test '(3 4 1 -8.4 7.2 4 1 1.2))
(exit)</
Sample output:
Line 2,201 ⟶ 4,172:
=={{header|Nim}}==
{{trans|Python}}
<
proc median(xs: seq[float]): float =
Line 2,211 ⟶ 4,182:
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:
Line 2,219 ⟶ 4,190:
=={{header|Oberon-2}}==
Oxford Oberon-2
<
MODULE Median;
IMPORT Out;
Line 2,301 ⟶ 4,272:
Out.Fixed(Median(ary,0,7),4,2);Out.Ln;
END Median.
</syntaxhighlight>
Output:
<pre>
Line 2,311 ⟶ 4,282:
=={{header|Objeck}}==
<
use Structure;
Line 2,343 ⟶ 4,314:
}
}
</syntaxhighlight>
=={{header|OCaml}}==
<
let median array =
let len = Array.length array in
Line 2,355 ⟶ 4,326:
median a;;
let a = [|4.1; 7.2; 1.7; 9.3; 4.4; 3.2|];;
median a;;</
=={{header|Octave}}==
Of course Octave has its own <tt>median</tt> 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.
<
if (numel(v) < 1)
y = NA;
Line 2,379 ⟶ 4,350:
disp(median(a))
disp(median2(b)) % 4.25
disp(median(b))</
=={{header|ooRexx}}==
<syntaxhighlight lang="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)
Line 2,419 ⟶ 4,390:
-- results for the compares
return (left - right)~sign
</syntaxhighlight>
=={{header|Oz}}==
<
fun {Median Xs}
Len = {Length Xs}
Line 2,434 ⟶ 4,405:
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]}}</
=={{header|PARI/GP}}==
Sorting solution.
<
vecsort(v)[#v\2]
};</
Linear-time solution, mostly proof-of-concept but perhaps suitable for large lists.
<
if(#v<15, return(vecsort(v)[k]));
my(u=List(),pivot,left=List(),right=List());
Line 2,463 ⟶ 4,434:
BFPRT(left, k)
)
};</
=={{header|Pascal}}==
{{works with|Free_Pascal}}
<
type
Line 2,523 ⟶ 4,494:
writeln;
writeln('Median: ', Median(A):7:3);
end.</
Output:
<pre>% ./Median
Line 2,534 ⟶ 4,505:
=={{header|Perl}}==
{{trans|Python}}
<
my @a = sort {$a <=> $b} @_;
return ($a[$#a/2] + $a[@a/2]) / 2;
}</
=={{header|Phix}}==
The obvious simple way:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">median</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">l</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">+</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])/</span><span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--</syntaxhighlight>-->
It is also possible to use the [[Quickselect_algorithm#Phix|quick_select]] routine for a small (20%) performance improvement,
which as suggested below may with luck be magnified by retaining any partially sorted results.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">medianq</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">l</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">quick_select</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">quick_select</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">+</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span> <span style="color: #000080;font-style:italic;">-- (or perhaps return {s,res})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--</syntaxhighlight>-->
=={{header|Phixmonti}}==
<syntaxhighlight lang="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 ?</syntaxhighlight>
=={{header|PHP}}==
This solution uses the sorting method of finding the median.
<
function median($arr)
{
Line 2,605 ⟶ 4,581:
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
</syntaxhighlight>
=={{header|Picat}}==
<syntaxhighlight lang="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).</syntaxhighlight>
{{out}}
<pre>[[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]</pre>
=={{header|PicoLisp}}==
<
(let N (length Lst)
(if (bit? 1 N)
Line 2,619 ⟶ 4,634:
(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:
<pre>2.00
Line 2,627 ⟶ 4,642:
=={{header|PL/I}}==
<
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;</
=={{header|PowerShell}}==
Line 2,640 ⟶ 4,654:
All statistical properties could easily be added to the output object.
<syntaxhighlight lang="powershell">
function Measure-Data
{
Line 2,710 ⟶ 4,724:
}
}
</syntaxhighlight>
<syntaxhighlight lang="powershell">
$statistics = Measure-Data 4, 5, 6, 7, 7, 7, 8, 1, 1, 1, 2, 3
$statistics
</syntaxhighlight>
{{Out}}
<pre>
Line 2,728 ⟶ 4,742:
</pre>
Median only:
<syntaxhighlight lang="powershell">
$statistics.Median
</syntaxhighlight>
{{Out}}
<pre>
4.5
</pre>
=={{header|Processing}}==
<syntaxhighlight lang="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;
}</syntaxhighlight>
{{Out}}
<pre>4.7
4.1</pre>
=={{header|Prolog}}==
<
length(L, Length),
I is Length div 2,
Line 2,745 ⟶ 4,776:
maplist(nth1, Mid, [S, S], X),
sumlist(X, Y),
Z is Y/2.</
=={{header|Pure}}==
Inspired by the Haskell version.
<
when len = # x;
mid = len div 2;
rem = len mod 2;
end;</
Output:<pre>> median [1, 3, 5];
3.0
> median [1, 2, 3, 4];
2.5
</pre>
=={{header|PureBasic}}==
<
If length = 0 : ProcedureReturn 0.0 : EndIf
SortArray(values(), #PB_Sort_Ascending)
Line 2,795 ⟶ 4,826:
Data.i 6
Data.d 4.1, 7.2, 1.7, 9.3, 4.4, 3.2
EndDataSection</
=={{header|Python}}==
<
srtd = sorted(aray)
alen = len(srtd)
Line 2,806 ⟶ 4,837:
print a, median(a)
a = (4.1, 7.2, 1.7, 9.3, 4.4, 3.2)
print a, median(a)</
=={{header|R}}==
Line 2,812 ⟶ 4,843:
{{trans|Octave}}
<
if ( length(v) < 1 )
NA
Line 2,831 ⟶ 4,862:
print(omedian(a))
print(median(b)) # 4.25
print(omedian(b))</
=={{header|Racket}}==
<
(define (median numbers)
(define sorted (list->vector (sort (vector->list numbers) <)))
Line 2,847 ⟶ 4,878:
(median '#()) ;; #f
(median '#(5 4 2 3)) ;; 7/2
(median '#(3 4 1 -8.4 7.2 4 1 1.2)) ;; 2.1</
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2016.08}}
<syntaxhighlight lang="raku" line>sub median {
my @a = sort @_;
return (@a[(*-1) div 2] + @a[* div 2]) / 2;
}</syntaxhighlight>
Notes:
* The <tt>div</tt> operator does integer division. The <tt>/</tt> operator (rational number division) would work too, since the array subscript automatically coerces to <tt>Int</tt>, but using <tt>div</tt> is more explicit (i.e. clearer to readers) as well as faster, and thus recommended in cases like this.
* The <tt>*</tt> inside the subscript stands for the array's length ([https://raku.org/language/subscripts.html#From_the_end see documentation]).
<br>
In a slightly more compact way:
<syntaxhighlight lang="raku" line>sub median { @_.sort[(*-1)/2, */2].sum / 2 }</syntaxhighlight>
=={{header|REBOL}}==
<
median: func [
"Returns the midpoint value in a series of numbers; half the values are above, half are below."
Line 2,866 ⟶ 4,915:
]
]
</syntaxhighlight>
=={{header|ReScript}}==
<syntaxhighlight lang="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]))</syntaxhighlight>
{{out}}
<pre>
$ bsc median.res > median.bs.js
$ node median.bs.js
4.4
4.25
</pre>
=={{header|REXX}}==
<
/* ══════════vector════════════ ══show vector═══ ════════show result═══════════ */
v= 1 9 2 4 ; say "vector" v; say 'median──────►' median(v); say
Line 2,893 ⟶ 4,974:
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. */</
{{out|output}}
<pre>
Line 2,910 ⟶ 4,991:
=={{header|Ring}}==
<
aList = [5,4,2,3]
see "medium : " + median(aList) + nl
Line 2,920 ⟶ 5,001:
return (srtd[alen/2] + srtd[alen/2 + 1]) / 2.0
else return srtd[ceil(alen/2)] ok
</syntaxhighlight>
=={{header|RPL}}==
≪ '''SORT'''
DUP SIZE 1 + 2 /
DUP2 FLOOR GET ROT ROT CEIL GET + 2 /
≫ ''''MDIAN'''' STO
<code>SORT</code> 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 [[Sorting algorithms/Bubble sort#RPL|here]].
=={{header|Ruby}}==
<
return nil if ary.empty?
mid, rem = ary.length.divmod(2)
Line 2,936 ⟶ 5,024:
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:
<
srtd = aray.sort
alen = srtd.length
(srtd[(alen-1)/2] + srtd[alen/2]) / 2.0
end</
=={{header|Run BASIC}}==
<
mem$ = "CREATE TABLE med (x float)"
#mem execute(mem$)
Line 2,975 ⟶ 5,063:
print " Median :";median;chr$(9);" Values:";a$
RETURN</
<pre>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
Line 2,987 ⟶ 5,075:
Sorting, then obtaining the median element:
<
// sort in ascending order, panic on f64::NaN
xs.sort_by(|x,y| x.partial_cmp(y).unwrap() );
Line 3,001 ⟶ 5,089:
let nums = vec![2.,3.,5.,0.,9.,82.,353.,32.,12.];
println!("{:?}", median(nums))
}</
{{out}}
Line 3,009 ⟶ 5,097:
{{works with|Scala|2.8}} (See the Scala discussion on [[Mean]] for more information.)
<
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 <tt>splitAt</tt> and <tt>last</tt> are O(n/2)
Line 3,022 ⟶ 5,110:
{{trans|Python}}
Using Rosetta Code's [[Bubble_Sort#Scheme|bubble-sort function]]
<
(* (+ (list-ref (bubble-sort l >) (round (/ (- (length l) 1) 2)))
(list-ref (bubble-sort l >) (round (/ (length l) 2)))) 0.5))</
Using [http://srfi.schemers.org/srfi-95/srfi-95.html SRFI-95]:
<
(* (+ (list-ref (sort l less?) (round (/ (- (length l) 1) 2)))
(list-ref (sort l less?) (round (/ (length l) 2)))) 0.5))</
=={{header|Seed7}}==
<
include "float.s7i";
Line 3,059 ⟶ 5,147:
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;</
=={{header|SenseTalk}}==
SenseTalk has a built-in median function. This example also shows the implementation of a customMedian function that returns the same results.
<syntaxhighlight lang="sensetalk">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</syntaxhighlight>
Output:
<syntaxhighlight lang="sensetalk">4.4
5
4.4
5</syntaxhighlight>
=={{header|Sidef}}==
<
var srtd = arry.sort;
var alen = srtd.length;
srtd[(alen-1)/2]+srtd[alen/2] / 2;
}</
=={{header|Slate}}==
<
[
s isEmpty
Line 3,079 ⟶ 5,190:
ifTrue: [(sorted middle + (sorted at: sorted indexMiddle - 1)) / 2]
ifFalse: [sorted middle]]
].</
<
inform: { 4.1 . 7.2 . 1.7 . 9.3 . 4.4 . 3.2 } median.</
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
<
median [
self size = 0
Line 3,099 ⟶ 5,210:
ifTrue: [ ^nil ]
]
].</
<
median displayNl.
{ 4.1 . 7.2 . 1.7 . 9.3 . 4.4 . 3.2 } asOrderedCollection
median displayNl.</
=={{header|Stata}}==
Use '''[https://www.stata.com/help.cgi?summarize summarize]''' to compute the median of a variable (as well as other basic statistics).
<
gen x=rbeta(0.2,1.3)
quietly summarize x, detail
display r(p50)</
Here is a straightforward implementation using '''[https://www.stata.com/help.cgi? sort]'''.
<
sort `1'
if mod(_N,2)==0 {
Line 3,127 ⟶ 5,238:
calcmedian x
display r(p50)</
=={{header|Swift}}==
===A full implementation===
<syntaxhighlight lang="swift">
// 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)})
}
}
</syntaxhighlight>
Usage:
<syntaxhighlight lang="swift">
var c: [Double] = (0...100).map {_ in Double.random(in: 0...100)}
print(c.median())
</syntaxhighlight>
=={{header|Tcl}}==
<
set list [lsort -real $args]
set len [llength $list]
Line 3,145 ⟶ 5,313:
}
puts [median 3.0 4.0 1.0 -8.4 7.2 4.0 1.0 1.2]; # --> 2.1</
=={{header|TI-83 BASIC}}==
Using the built-in function:
<
=={{header|TI-89 BASIC}}==
<
=={{header|Ursala}}==
the simple way (sort first and then look in the middle)
<
#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
<
examples =
Line 3,172 ⟶ 5,337:
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:
<pre>
(4.050000e+00,5.700000e+00)</pre>
==
Requires <code>--pkg posix -X -lm</code> compilation flags in order to use POSIX qsort, and to have access to math library.
<
double a = *(double*) a_ref;
double b = *(double*) b_ref;
Line 3,198 ⟶ 5,363:
double[] array2 = {2, 4, 6, 1, 7, 3, 5, 8};
print(@"$(median(array1)) $(median(array2))\n");
}</
=={{header|VBA}}==
{{trans|Phix}}
Uses [[Quickselect_algorithm#VBA|quick select]].
<syntaxhighlight lang="vb">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</syntaxhighlight>{{out}}
<pre> 3,5 </pre>
=={{header|Vedit macro language}}==
Line 3,206 ⟶ 5,394:
The result is returned in text register @10. In case of even number of items, the lower middle value is returned.
<
EOF Goto_Line(Cur_Line/2)
Reg_Copy(10, 1)</
=={{header|V (Vlang)}}==
<syntaxhighlight lang="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
}</syntaxhighlight>
{{out}}
<pre>
2
3
</pre>
If you use math.stats module the list parameter must be sorted
<syntaxhighlight lang="text">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
}</syntaxhighlight>
=={{header|Wortel}}==
<
; iterative
med1 &l @let {a @sort l s #a i @/s 2 ?{%%s 2 ~/ 2 +`-i 1 a `i a `i a}}
Line 3,224 ⟶ 5,441:
!med2 [4 5 2 1]
]]
}</
Returns: <pre>[2 3 2 3]</pre>
=={{header|Wren}}==
{{libheader|Wren-sort}}
{{libheader|Wren-math}}
{{libheader|Wren-queue}}
<syntaxhighlight lang="wren">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()
}</syntaxhighlight>
{{out}}
<pre>
4
4
4
2.1
2.1
2.1
</pre>
=={{header|XPL0}}==
<syntaxhighlight lang "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);
]</syntaxhighlight>
{{out}}
<pre>
4.00000
2.10000
</pre>
=={{header|Yabasic}}==
{{trans|Lua}}
<
return int(x + .05)
end sub
Line 3,285 ⟶ 5,574:
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
</syntaxhighlight>
=={{header|zkl}}==
Using the [[Quickselect algorithm#zkl]] for O(n) time:
<syntaxhighlight lang="zkl">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;
}</syntaxhighlight>
<syntaxhighlight lang="zkl">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</syntaxhighlight>
=={{header|Zoea}}==
<syntaxhighlight lang="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
</syntaxhighlight>
=={{header|Zoea Visual}}==
[http://zoea.co.uk/examples/zv-rc/Median.png Median]
=={{header|zonnon}}==
<
module Averages;
Line 3,358 ⟶ 5,676:
writeln(Median(ary):10:2)
end Averages.
</syntaxhighlight>
<pre>
4
Line 3,365 ⟶ 5,683:
</pre>
|