percent.c revision 23bb9b106adcf32c41e1700d0eb17939e55cd6bb
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 */
18unsigned 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
35main(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