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 */
e2p_percent(int percent,unsigned int base)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
main(int argc,char ** argv)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