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