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