percent.c revision d1154eb460efe588eaed3d439c1caaca149fa362
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 */
21unsigned 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
38main(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