>What human can understand it?
Lets start with Wilson's midpoint, since that's just high school math.
def mid(upvotes:Int, downvotes:Int) = {
val total = upvotes+downvotes+0.0
val up = upvotes/total
val half = 0.5
val a = total/(4+total)
val b = 4/(4+total)
a * up + b * half
}
So there are two weights a and b. Using these weights, the midpoint is a weighted average of half and the proportion of upvotes.
It should be very clear that if the total becomes large, a goes to 1 and b to zero. At that point you end up using the proportion of upvotes, just like Amazon.
Now, lets bring in the entire confidence interval.
def wilson(upvotes:Int, downvotes:Int) = {
val z = 1.96
val n = upvotes+downvotes+0.0d
val phat = upvotes/n
val lower = (phat + z*z/(2*n) - z * sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
val upper = (phat + z*z/(2*n) + z * sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
(lower,upper)
}
Using the author's data points, the results look like this:
val itemVotes = List((600,400),(5500,4500),(2,0), (100,1))
itemVotes.foreach( x => {
val s = mid(x._1,x._2)
val w = wilson(x._1,x._2)
printf("Up:%5d\tDown:%5d\tMid:%.3f\tW:[%.3f,%.3f]\n",
x._1, x._2,s,w._1,w._2)
})
scala> Up: 600 Down: 400 Mid:0.600 W:[0.569,0.630]
Up: 5500 Down: 4500 Mid:0.550 W:[0.540,0.560]
Up: 2 Down: 0 Mid:0.667 W:[0.342,1.000]
Up: 100 Down: 1 Mid:0.971 W:[0.946,0.998]
Basically, we prefer the lower bound of the confidence interval instead of the midpoint of that same interval.