Task

Write a function to verify that a given distribution of values is uniform by using the 




χ

2




{\displaystyle \chi ^{2}}

 test to see if the distribution has a likelihood of happening of at least the significance level (conventionally 5%).

The function should return a boolean that is true if the distribution is one that a uniform distribution (with appropriate number of degrees of freedom) may be expected to produce.



Reference

   an entry at the MathWorld website:   chi-squared distribution.


with javascript_semantics
function f(atom aa1, t)
    return power(t, aa1) * exp(-t)
end function 
 
function simpson38(atom aa1, a, b, integer n)
    atom h := (b-a)/n,
         h1 := h/3,
         tot := f(aa1,a) + f(aa1,b)
    for j=3*n-1 to 1 by -1 do
        tot += (3-(mod(j,3)=0)) * f(aa1,a+h1*j)
    end for
    return h*tot/8
end function
 
--<copy of gamma from Gamma_function#Phix>
sequence c = repeat(0,12)
 
function gamma(atom z)
    atom accm = c[1]
    if accm=0 then
        accm = sqrt(2*PI)
        c[1] = accm
        atom k1_factrl = 1  -- (k - 1)!*(-1)^k with 0!==1
        for k=2 to 12 do
            c[k] = exp(13-k)*power(13-k,k-1.5)/k1_factrl
            k1_factrl *= -(k-1)
        end for
    end if
    for k=2 to 12 do
        accm += c[k]/(z+k-1)
    end for
    accm *= exp(-(z+12))*power(z+12,z+0.5) -- Gamma(z+1)
    return accm/z
end function
--</copy of gamma>

function gammaIncQ(atom a, x)
    atom aa1 := a-1,
         y := aa1,
         h := 1.5e-2
    while f(aa1,y)*(x-y) > 2e-8 and y < x do
        y += 0.4
    end while
    if y > x then y = x end if
    return 1 - simpson38(aa1,0,y,floor(y/h/gamma(a)))
end function
 
function chi2ud(sequence ds)
    atom expected = sum(ds)/length(ds),
         tot = sum(sq_power(sq_sub(ds,expected),2))
    return tot/expected
end function
 
function chi2p(integer dof, atom distance)
    return gammaIncQ(0.5*dof,0.5*distance)
end function
 
constant sigLevel = 0.05
 
procedure utest(sequence dset)
    printf(1,"Uniform distribution test\n")
    integer tot = sum(dset),
            dof := length(dset)-1
    atom dist := chi2ud(dset),
         p := chi2p(dof, dist)
    bool sig := p < sigLevel
    printf(1," dataset: %v\n",{dset})
    printf(1," samples:                   %d\n", tot)
    printf(1," categories:                %d\n", length(dset))
    printf(1," degrees of freedom:        %d\n", dof)
    printf(1," chi square test statistic: %g\n", dist)
    printf(1," p-value of test statistic: %g\n", p)
    printf(1," significant at %.0f%% level?   %t\n", {sigLevel*100, sig})
    printf(1," uniform?                   %t\n",not sig)
end procedure
 
utest({199809, 200665, 199607, 200270, 199649})
utest({522573, 244456, 139979, 71531, 21461})
