#!/usr/bin/env python """Report on the 'central tendency' of a collection of numbers from STDIN This script redefines several builtin functions with obvious names to variables reflecting the operation of those functions. The switches that may be given are simply the names of variables so defined, and it would be inconvenient to make user remember a switch spelling other than, e.g. '-sum' or '-max'. Usage: average [switches] < LIST-OF-NUMS Switches (may specify zero or more switches): -N, --count How many numbers were passed in? --product, -Pi Product of numbers --sum, --total Sum of numbers -q, --am, --arithmetic Arithmetic mean of numbers --hm, --harmonic Harmonic mean of numbers --med, --median Median of numbers --gm, --geometric Geometric mean of numbers --min, --smallest Smallest number passed in --max, --largest Largest number passed in -h, --help This display """ import sys from operator import mul if '-h' in sys.argv or '--help' in sys.argv: print __doc__ sys.exit() NaN = float("NaN") try: nums = map(float, sys.stdin.read().split()) except ValueError, e: print "nan "*len(sys.argv[1:]) if sys.argv[1:] else "ValueError: %s" % e sys.exit() if not nums: print "nan "*len(sys.argv[1:]) if sys.argv[1:] else "No numbers on STDIN" sys.exit() prod = lambda lst: reduce(mul, lst) product = Pi = prod(nums) N = count = len(nums) total = sum(nums) q = am = arithmetic = mean = total / N hm = harmonic = N / sum([1/x for x in nums]) if 0 not in nums else NaN med = median = sorted(nums)[N/2] # Since we may be dealing with a large number of small numbers, the GM multiply # can reach FP rounding errors. Scale each number to approx one, then unscale gm = geometric = prod([n/am for n in nums]) ** (1./N) * am min = smallest = min(nums) max = largest = max(nums) sum = total prod = product if sys.argv[1:]: for var in sys.argv[1:]: print eval(var.replace('-','')), print else: print "Averages of %d numbers" % N print "Arithmetic Mean: %f" % am print "Geometric Mean: %f" % gm print "Harmonic Mean: %f" % hm print "Median: %f" % med print "Smallest item: %f" % min print "Largest item: %f" % max