我正在根据无符号整数编写图像类。我目前使用uint8_t和uint16_t缓冲区用于8位和16位RGBA像素,并且要从16位转换为8位,我只需要取16位值,除以std :: numeric_limits< uint16_t> :: max()转换为double,然后乘以255。
但是,如果我想为每个RGBA组件创建一个64位无符号整数的图像(我知道,它非常高),我怎样才能找到0到1之间的浮点数/双精度值表示0和最大uint64_t之间的距离是多少?我假设转换为双精度不会起作用,因为双精度通常是64位浮点数,并且你无法捕获64位浮点数中的所有64位无符号整数值。在不转换为浮点数/双打的情况下进行划分只会给我0或有时1。
找到介于0和1之间的浮点值的最准确方法是什么,它表示0和无符号64位值之间的最大距离是多少?
答案 0 :(得分:4)
找到介于0和1之间的浮点值的最准确方法是什么,它表示0和无符号64位值之间的最大距离是多少?
要将[0 ... 2 64 )范围内的整数值映射到[0 ... 1.0),可以直接进行。
从uint64_t
转换为double
。
按2 64 @Mark Ransom
缩放#define TWO63 0x8000000000000000u
#define TWO64f (TWO63*2.0)
double map(uint64_t u) {
double y = (double) u;
return y/Two64f;
}
意志地图
[2 63 ... 2 64 )至[0.5 ... 1.0)范围内的整数值:2 52 不同double
值
整数值在[2 62 ... 2 63 )至[0.25 ... 0.5):2 52 不同{{1值
[2 61 ... 2 62 )至[0.125 ... 0.25)范围内的整数值:2 52 不同{{1值
...
整数值在[2 52 ... 2 53 )至[2 -12 ... 2 -11 < / sup>):2 52 不同的double
值
整数值在[0 ... 2 52 )至[2 -13 ... 2 -12 )范围内:2 52 不同的double
值。
将[0 ... 2 64 )范围内的整数值映射到[0 ... 1.0]更加困难。 (请注意double
与double
。
答案 1 :(得分:2)
您可以从Java java.util.Random nextDouble()
方法的以下代码开始。它需要53位并从中形成一个双重:
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
我将使用long的最重要的26位作为移位值,接下来的27位填充低位。这会丢弃输入的最低有效64-53 = 11位。
如果区分非常小的值特别重要,您还可以使用次正规数,nextDouble()
不返回。
答案 2 :(得分:1)
OP要求使用C ++,所以去了:
(假设编译器知道类型__int64
,这很可能是Visual Studio风格的。)
double asDouble(unsigned __int64 v)
{
return ((__int64)(v >> 11)) / (double)(1L << 53);
}
或者,如果您不介意时髦的演员表:
double asDouble(unsigned __int64 v)
{
// the 0x3FF sets the exponent to the 0..1 range.
unsigned __int64 vv == (v >> 11) | (0x3FFL << 53);
return *(double*)&vv;
}