float_bucket.c
text/x-c-code
Filename: float_bucket.c
Type: text/x-c-code
Part: 1
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
/*
* The two expressions "high - low" can result in +inf if "high" and
* "low" are have a distance exceeding DBL_MAX. Similarly, the
* expression "oper - low" can be +inf if "oper" and "low" differs
* by more than DBL_MAX.
*/
int width_bucket_orig(double oper, double low, double high, int count) {
return ((double)count * (oper - low) / (high - low)) + 1;
}
int width_bucket_new(double oper, double low, double high, int count) {
const double bucket_size = (high / 2 - low / 2);
const double bucket_pos = (oper / 2 - low / 2);
return count * (bucket_pos / bucket_size) + 1;
}
static struct value {
double operand;
double low;
double high;
int count;
} values[] = {
{10.4, -DBL_MAX, DBL_MAX, 10},
{-DBL_MAX / 2, -DBL_MAX, DBL_MAX, 10},
{DBL_MAX / 2, -DBL_MAX, DBL_MAX, 10},
{10.4, -DBL_MAX, DBL_MAX, 12},
{-DBL_MAX / 2, -DBL_MAX, DBL_MAX, 12},
{DBL_MAX / 2, -DBL_MAX, DBL_MAX, 12},
{10.4, -DBL_MAX, DBL_MAX, 1},
{-DBL_MAX / 2, -DBL_MAX, DBL_MAX, 1},
{DBL_MAX / 2, -DBL_MAX, DBL_MAX, 1},
{10.4, -DBL_MAX, DBL_MAX, 2},
{-DBL_MAX / 2, -DBL_MAX, DBL_MAX, 2},
{DBL_MAX / 2, -DBL_MAX, DBL_MAX, 2},
{5.35, 0.024, 10.06, 5},
{DBL_MIN, -2 * DBL_MIN, 2 * DBL_MIN, 4},
{-DBL_MIN, -2 * DBL_MIN, 2 * DBL_MIN, 4},
{DBL_MIN, -3 * DBL_MIN, 3 * DBL_MIN, 4},
{-DBL_MIN, -3 * DBL_MIN, 3 * DBL_MIN, 4},
{DBL_MIN, -3 * DBL_MIN, 3 * DBL_MIN, 6},
{-DBL_MIN, -3 * DBL_MIN, 3 * DBL_MIN, 6},
};
void print_result(double oper, double low, double high, int count) {
printf(
"% 2.5e, low: % 2.5e, high: % 2.5e, count: % 2d --> orig: % 2d, new: % "
"2d\n",
oper,
low,
high,
count,
width_bucket_orig(oper, low, high, count),
width_bucket_new(oper, low, high, count));
}
int main(int argc, char *argv[]) {
printf("DBL_MAX: %e, DBL_MIN: %e\n", DBL_MAX, DBL_MIN);
if (argc == 1) {
int i;
for (i = 0; i < sizeof(values) / sizeof(*values); ++i)
print_result(
values[i].operand, values[i].low, values[i].high, values[i].count);
} else if (argc == 5) {
print_result(strtod(argv[1], NULL),
strtod(argv[2], NULL),
strtod(argv[3], NULL),
strtol(argv[4], NULL, 0));
} else {
fprintf(stderr, "Usage: <oper> <low> <high> <count>\n");
exit(2);
}
}