我需要将0,1范围内的32位浮点值x转换为0,255范围内的8位无符号整数y。
我在一些C代码中找到的一个公式是:y = (uint8)(255.99998f*x)。
这提供了所需的转换,但存在一个问题。
转换为0.75产率191,转换0.25产率63。而0.75+0.25 = 1,191+63 = 254,而不是所需的255。
与0.5相同的问题被转换为127。0.5 + 0.5 =1和127+127= 254而不是255。
因此,存在舍入错误。
这能避免吗?如果是,怎么做?
发布于 2021-03-31 13:35:18
与0.5相同的问题被转换为127。0.5 + 0.5 =1和127+127= 254而不是255。
任何映射都不能满足这一要求,因为255/2不能表示为整数。您必须决定这个映射对您意味着什么以及它需要什么属性,但是对整数的映射不能满足这一点。
如果您选择了一个如您在问题中所示的地板映射,那么0.5f->127,在这种情况下,您的算法或程序可能会解释这一点,以定义128个元素的[0-127]范围--正好是[0-255]中256个元素的一半,因为剩下的128-255元素也有128个元素。
但是,如果您选择一个分析映射,如
y = round(255*x);这提供了最精确的数值--输出的值总是与输入值最接近的整数。对于0.5f的值,这将生成128,它正好是输出范围内回收箱数量的一半。在这种情况下,您的算法可能会将其解释为范围内的元素数,即输入范围的一半。这真的取决于你设计的算法和映射的解释围绕着放弃32位浮点数的分辨率所施加的限制。
最终,[0.0-1.0]是关于测量一些东西,[0-255]是关于计数一些东西..。只有你知道你在测量什么,你在计算什么,所以我们不能真正为你做出这个决定。
如果您的应用程序是度量式的,那么round(255*x)将生成与输入浮点数最接近的整数--例如,0.0039062的值在完美映射到1的0.001%以内,将映射到1。
如果您的应用程序是一个类似计数的应用程序,并且您更感兴趣的是同样地绑定浮点值,那么地板映射(就像您最初的建议)将把相同范围的输入映射到每个bin。使用round方程将0 bin和255 bin映射到其余回收箱范围的一半。使用地板映射产生的输入范围与输出箱的分布相等,但牺牲了数值精度。例如,上面的0.0039062值示例将映射到0,尽管它是您认为是1值的99.99%。
完全由您来决定哪个映射对您的特定应用程序有意义。
发布于 2021-03-31 14:23:10
您将无法将封闭段0.0、1.0准确地表示为0,255段。最明显的问题是0.5 + 0.5 = 1.0。因此,如果1.0是由255表示的,则0.5不能完全表示。
真正的问题是32位浮点数是用IEE 754二进制32格式表示的。因此,您将从[0.0,1.0 ](半开放段)到0,255段中找到一个本机注入,方法是取二进制表示中最具代表性的位(方便地移动),并接受在限制为1.0时表示为256。
然后,所有分母为2幂的分数都被精确地表示: 0.5为128,0.25为64,0.75为192,但试图很好地将0.0、1.0到0,255映射为从0,256到0,255之间的一个很好的关系。
https://stackoverflow.com/questions/66888344
复制相似问题