无符号字符类型的负数

Negative numbers of type unsigned char

本文关键字:类型 字符 无符号      更新时间:2023-10-16

我从头开始实现 2D 相关代码,我有一个简单的 3x3 图像矩阵,类型为无符号字符:

 unsigned char Image = [184   0   35
                        48   107  193
                        29   166  32]

我的关联内核

             Kernel = [-1 0 1]  

现在,当我执行相关时,第一行的结果在数学上是 -149,但打印的结果是 107(2 的补码)。

unsigned char res = -1.F *(Kernel[i-1]) + (Kernel[i+1]); 

这不是一个错误吗?如何将结果保存为 -149 但类型仍保留为无符号字符?我知道我的问题可能不合适,因为无符号字符的范围是 0 到 255,但我想确定我是否遗漏了什么。我也知道负数被转换为 2 的补码。
顺便说一句,这不是任何家庭作业,我只是从图像处理的角度研究C/C++。

如何将结果保存为 -149 但类型仍保留为无符号字符?

别这样。使用有符号整数类型。

如果增加的内存使用量不是问题,请使用int
如果做不到这一点,请使用 short .

在范围 [0 max] 的图像上计算梯度 [-X 0 X] 时,结果在范围 [-X max, X max] 范围内。根据您的需求和约束,有不同的方法可以处理它:

  1. 如果您没有内存问题,则可以增加编码(字节 -> 短,短 -> int)。
  2. 如果你感兴趣,但梯度强度而不是它的符号,你首先应用一个绝对值以获得新的结果范围[0,X*max],然后你去应用第三个解决方案
  3. 您拉伸
  4. 结果以适合所需的范围,这意味着您应用直方图拉伸(线性函数):[-X 最大值,X最大值] -> [0 最大值]。不幸的是,此解决方案会失去很多精度。以您为例,此解决方案会损失一半的精度(从 [-255, 255)] 到 [0, 255]),除非您之前应用点 2。

现在,当我执行相关时,第一行的结果在数学上是 -149,但打印的结果是 107(2 的补码)。 这不是一个错误吗?

unsigned char res = -1.F *(Kernel[i-1]) + (Kernel[i+1]); 

在无符号变量(如 res)中保存负值不会更改res的类型。 这是永远unsigned char. 负值通过反复添加/(或减去)UCHAR_MAX + 1 (256) 进行转换,直到它在 unsigned char 范围内或在这种情况下:107 .

若要保存负值并保留res中的负值,请使用满足范围要求的有符号类型:

Type          Range of Type 
signed char   at least [-127 to 127]      Varies by platform
signed short  at least [-32767 to 32767]  Varies by platform
int8_t        exactly  [-128 to 127]
int16_t       exactly  [-32768 to 32767]