是否有函数可以检索范围内可用非重复值的数量

Is there a function to retrieve the number of available distinct values within a range?

本文关键字:函数 检索 范围内 是否      更新时间:2023-10-16

我在我正在制作的应用程序中使用双精度浮点变量。

我规范化了一些值范围。从(例如;我有很多范围)-48.048.00.01.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,下面是-INFINF

的有效。
// 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';
}