我正在写一个基于无符号整数的图像类。我目前对8位和16位RGBA像素使用uint8_t和uint16_t缓冲,要从16位转换到8位,我只需将16位值除以std::numeric_limits
但是,如果我想要一个图像,每个RGBA分量都是64位无符号整数(我知道,这个数字高得离谱),我该如何在0和1之间找到一个浮点/双精度数,来表示我的像素值在0和最大uint64_t之间有多远呢?我认为转换为double是行不通的,因为double通常是64位浮点型,并且您不能在64位浮点型中捕获所有64位无符号整数值。没有转换成浮点数/双精度数的除法只能得到0或者有时是1。
查找0和1之间的浮点值的最准确方法是什么,该浮点值表示0和无符号64位值的最大值之间的距离?
查找0和1之间的浮点值的最准确方法是什么,该浮点值表示0和无符号64位值的最大值之间的距离?
可以直接将[0…264)到[0…1.0)范围内的整数值映射。
>
从 uint64_t
转换为双倍
。
按264 @Mark Ransom缩放
#define TWO63 0x8000000000000000u
#define TWO64f (TWO63*2.0)
double map(uint64_t u) {
double y = (double) u;
return y/Two64f;
}
遗嘱地图
范围内的整数值 [263...264) 至 [0.5 ...1.0):252 种不同的双精度
值。范围内的
整数值 [262...263) 至 [0.25 ...0.5):252 种不同的双精度
值。范围内的
整数值 [261...262) 至 [0.125 ...0.25):252 个不同的双精度
值。
。
范围内的整数值 [252...253) 至 [2-12 ...2-11):252 种不同的双精度
值。
介于 [0...252) 到 [2-13 ...2-12):252 种不同的双精度
值。
要映射范围[0...264)到[0...1.0]比较难。(注意< code>]与< code>)。
[2021年2月]我认为这个答案需要重新解释上边缘情况。返回的潜在值包括1.0。
您可以从以下代码开始Java的java.util.随机<代码>next双精度()方法。它需要53位并从中形成一个双精度:
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
我会使用长整型中最重要的 26 位作为移位值,接下来的 27 位来填充低阶位。这将丢弃最不重要的 64-53 = 11 位输入。
如果区分非常小的值特别重要,您也可以使用次正规数,这是< code>nextDouble()不会返回的。
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;
}