С почти все программирования чисел с плавающей запятой, значения распределены логарифмически. Поэтому сначала возьмите значение log()
значения, чтобы начать картографирование, обращая внимание на проблемы, связанные с граничным случаем.
double map(double x, double x0, double x1, double y0, double y1) {
return (x - x0)/(x1 - x0) * (y1 - y0) + y0;
}
double noramlize01(double x) {
assert(x == x); // fail is x is NaN
// These values only need to be calculated once.
double logxmin = log(DBL_TRUE_MIN); // e.g. -323.306...
double logxmax = log(DBL_MAX); // e.g. 308.254...
double y;
if (x < -DBL_MAX) y = 0.0;
else if (x < 0.0) {
y = map(log(-x), logxmax, logxmin, nextafter(0.0,1.0), nextafter(0.5,0.0));
} else if (x == 0.0) {
y = 0.5;
} else if (x <= DBL_MAX) {
y = map(log(x), logxmin, logxmax, nextafter(0.5,1.0), nextafter(1.0,0.5));
} else {
y = 1.0;
}
return y;
}
double round_n(double x, unsigned n) {
return x * n;
}
void testr(double x) {
printf("% 20e %#.17g\n", x, noramlize01(x));
//printf("% 20e %.17f\n", -x, noramlize01(-x));
}
int main(void) {
double t[] = {0.0, DBL_TRUE_MIN, DBL_MIN, 1/M_PI, 1/M_E,
1.0, M_E, M_PI, DBL_MAX, INFINITY};
for (unsigned i = sizeof t/sizeof t[0]; i > 0; i--) {
testr(-t[i-1]);
}
for (unsigned i = 0; i < sizeof t/sizeof t[0]; i++) {
testr(t[i]);
}
}
Пример вывода
-inf 0.0000000000000000
-1.797693e+308 4.9406564584124654e-324
-3.141593e+00 0.24364835649917244
-2.718282e+00 0.24369811843639441
-1.000000e+00 0.24404194470924687
-3.678794e-01 0.24438577098209935
-3.183099e-01 0.24443553291932130
-2.225074e-308 0.48760724499523350
-4.940656e-324 0.49999999999999994
-0.000000e+00 0.50000000000000000
0.000000e+00 0.50000000000000000
4.940656e-324 0.50000000000000011
2.225074e-308 0.51239275500476655
3.183099e-01 0.75556446708067870
3.678794e-01 0.75561422901790065
1.000000e+00 0.75595805529075311
2.718282e+00 0.75630188156360556
3.141593e+00 0.75635164350082751
1.797693e+308 0.99999999999999989
inf 1.0000000000000000
Ничего себе! это действительно выглядит здорово, но я немного застрял в этой части «union {d; i64} = x», так как я понимаю, что C++ разбивает число на объединение, но в JS я его не реализовал. в любом случае выглядит, как этот код отлично работает в JS https://jsfiddle.net/p1ratrulezzz/qz5nzry8/ – P1ratRuleZZZ