Home | History | Annotate | Download | only in e2p
      1 /*
      2  * percent.c		- Take percentage of a number
      3  *
      4  * Copyright (C) 2006  Theodore Ts'o <tytso (at) mit.edu>
      5  *
      6  * %Begin-Header%
      7  * This file may be redistributed under the terms of the GNU Library
      8  * General Public License, version 2.
      9  * %End-Header%
     10  */
     11 
     12 #include "config.h"
     13 #include "e2p.h"
     14 
     15 #include <stdlib.h>
     16 
     17 /*
     18  * We work really hard to calculate this accurately, while avoiding
     19  * an overflow.  "Is there a hyphen in anal-retentive?"  :-)
     20  */
     21 unsigned int e2p_percent(int percent, unsigned int base)
     22 {
     23 	unsigned int mask = ~((1 << (sizeof(unsigned int) - 1) * 8) - 1);
     24 
     25 	if (!percent)
     26 		return 0;
     27 	if (100 % percent == 0)
     28 		return base / (100 / percent);
     29 	if (mask & base)
     30 		return (base / 100) * percent;
     31 	return base * percent / 100;
     32 }
     33 
     34 #ifdef DEBUG
     35 #include <unistd.h>
     36 #include <stdio.h>
     37 
     38 main(int argc, char **argv)
     39 {
     40 	unsigned int base;
     41 	int percent;
     42 	char *p;
     43 	int log_block_size = 0;
     44 
     45 	if (argc != 3) {
     46 		fprintf(stderr, "Usage: %s percent base\n", argv[0]);
     47 		exit(1);
     48 	}
     49 
     50 	percent = strtoul(argv[1], &p, 0);
     51 	if (p[0] && p[1]) {
     52 		fprintf(stderr, "Bad percent: %s\n", argv[1]);
     53 		exit(1);
     54 	}
     55 
     56 	base = strtoul(argv[2], &p, 0);
     57 	if (p[0] && p[1]) {
     58 		fprintf(stderr, "Bad base: %s\n", argv[2]);
     59 		exit(1);
     60 	}
     61 
     62 	printf("%d percent of %u is %u.\n", percent, base,
     63 	       e2p_percent(percent, base));
     64 
     65 	exit(0);
     66 }
     67 #endif
     68