我在我正在制作的应用程序中使用双精度浮点变量。
我规范化了一些值范围。从(例如;我有很多范围)-48.0
到48.0
到0.0
到1.0
,使用这个简单的函数:
double ToNormalizedParam(double nonNormalizedValue, double min, double max, double shape) {
return pow((nonNormalizedValue - min) / (max - min), 1.0 / shape);
}
我想知道从一个范围映射到另一个范围的可用值和不同值的差异。
C++是否有现成的功能?我看过numeric_limits
,但我找不到任何有用的东西。
C++是否有现成的功能?
也许。 如果没有,很容易形成一个函数来为每个double
值分配序列号。
假设字节序和大小的FP/整数匹配,典型的FP布局如double64,下面是-INF
到INF
// Return a sequence number for each `double` value.
// Numerically sequential `double` values will have successive (+1) sequence numbers.
uint64_t double_sequence(double x) {
uint64_t u64;
memcpy(&u64, &x, sizeof u64);
if (u64 & 0x8000000000000000) {
u64 ^= 0x8000000000000000;
return 0x8000000000000000 - u64;
}
return u64 + 0x8000000000000000;
}
是否有函数可以检索范围内可用非重复值的数量?
只需减去序列号即可。 +1 或 -1 取决于是开放范围还是封闭范围。
double_sequence(1.0) - double_sequence(0.0) + 1 --> 0x3ff0000000000001
double_sequence(48.0) - double_sequence(-48.0) + 1 --> 0x8090000000000001
笔记:
请记住,FP 在 2 的幂内整体和线性分布。
对于大约一半的FP,|x| < 1.0
.
FP 编号 0.5 到 1.0 与 16.0 到 32.0 之间的 FP 数字一样多。[-48.0 ... 48.0]
范围内的double
数是[0.0 ... 1.0]
数的两倍以上,这主要是由于负值。
给定一个正 IEEE 754 双精度浮点数,具有指数e
和尾数m
,两者都被解释为整数,小于它但大于零的不同值(不包括非规范化值)将正好m + (e - 1) * 2^52
。
可以这样提取
#include<iostream>
#include<tuple>
#include<cstdint>
#include<cstring>
using std::uint64_t;
std::tuple<uint64_t, uint64_t, uint64_t> explode(double d)
{
static_assert(sizeof(double) == 8);
uint64_t u;
std::memcpy(&u, &d, sizeof(d));
return { (u & 0x8000000000000000) >> 63,
(u & 0x7FF0000000000000) >> 52,
u & 0x000FFFFFFFFFFFFF };
}
uint64_t distinct(double d)
{
auto [_, e, m] = explode(d);
return m + ((e - 1) << 52);
}
int main()
{
std::cout << "[-48, 48]: " << 2 * distinct(48) << "n[0, 1]: " << distinct(1) << 'n';
}
住