1 /* 2 * percent.c - Take percentage of a number 3 * 4 * Copyright (C) 2006 Theodore Ts'o <tytso@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