123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <math.h>
- #define max(a,b) ({ \
- __typeof__ (a) _a = (a); \
- __typeof__ (b) _b = (b); \
- _a > _b ? _a : _b; \
- })
- void usage(FILE *out, const char *name) {
- fprintf(out, "Usage: %s n p\n", name);
- fprintf(out, "\n n: Number of reviews\n p: Percent positive\n");
- }
- double wilson_lower(long n, double p) {
- // https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval_with_continuity_correction
- double z = 1.96; // Let's use a good ol' 95% CI
- double w = (2.0*n*p + pow(z,2) - (1.0 + z*sqrt(pow(z,2)-1.0/n+4*n*p*(1-p)+(4*p-2))))
- /(2.0*((double)n+pow(z,2)));
- return(max(0.0, w));
- }
- int score(int argc, char **argv) {
- if(argc != 3) {
- usage(stderr, argv[0]);
- exit(1);
- }
- long n = 0;
- char *endptr = NULL;
- errno = 0;
- n = strtol(argv[1], &endptr, 10);
- if(errno != 0) {
- fprintf(stderr, "While parsing '%s', got error %d: %s\n", argv[1], errno, strerror(errno));
- usage(stderr, argv[0]);
- exit(1);
- }
- if(*endptr != '\0') {
- fprintf(stderr, "Error: '%s' is not numeric.\n", argv[1]);
- usage(stderr, argv[0]);
- exit(1);
- }
- if(n <= 0) {
- fprintf(stderr, "Error: got a non-positive number of reviews: %ld.\n", n);
- usage(stderr, argv[0]);
- exit(1);
- }
- double p = 0;
- endptr = NULL;
- errno = 0;
- p = strtod(argv[2], &endptr);
- if(errno != 0) {
- fprintf(stderr, "While parsing '%s', got error %d: %s\n", argv[1], errno, strerror(errno));
- usage(stderr, argv[0]);
- exit(1);
- }
- if(*endptr != '\0') {
- fprintf(stderr, "Error: '%s' is not numeric.\n", argv[2]);
- usage(stderr, argv[0]);
- exit(1);
- }
- if(p < 0 || p > 100) {
- fprintf(stderr, "Got a percentage of %0.1f, which is not between 0.0%% and 100.0%%\n", p);
- usage(stderr, argv[0]);
- exit(1);
- }
- double lower = wilson_lower(n, p/100.0);
- printf("%f\n", 1.0/(1.0-lower));
- return 0;
- }
- int main(int argc, char **argv) {
- if(argc < 2) {
- usage(stderr, argv[0]);
- exit(1);
- }
- score(argc, argv);
- // TODO: add another subcommand for testing hypothesis of difference between sellers
- return 0;
- }
|