计算机存储数据时,默认是存储数据的补码。有符号的数粗存在符号位(最高位)。

这里就会提到原码、反码、补码的概念。

原码:用符号位和数值表示带符号数,正数的符号位用“0”表示,负数的符号位用“1”表示,数值部分用二进制形式表示。
反码:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反。
补码:正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.

下位机上传有符号数时,直接上传的是补码。上位机解析时,需要手动转换:

一、当数为负数时。

0.获取该数据的补码,去掉最高位(符号位)并将其合并到一个结构体中(数据通信一般以字节为单位)。

1.空位(不用的位)补全,高位不用的置1。

2.将补码-1

3.然后再取反

4.乘上比例尺与-1

二、当数为正数时。

0.获取该数据的补码,去掉最高位(符号位)并将其合并到一个结构体中(数据通信一般以字节为单位)。

1.乘上比例尺

下位机上传的数据中有8个字节,其中第4(从0开始)字节的低四位和第5字节的高7位组成一个参数,这个参数是有符号的数据,与整数之间的比例尺是0.1。要求解析出该参数。

 				// 获取数据
                byte[] data = new byte[8];
                data = GetDataFromUsb();
                // 解析数据
                // 当上传的数据为负数时
                if ((UInt16)(data[4] & 0x08) == 0x08)
                    // 去掉最高位获取数据
                    UInt16 s = (UInt16)(((data[4] & 0x07) << 7) + (UInt16)((data[5] >> 1) & 0x7F));
                    // 空位补全,高位不用的置1
                    UInt16 s1 = (UInt16)(s | 0xFC00);
                    // 补码-1
                    UInt16 s2 = (UInt16)(s1 - 1);
                    // 取反
                    UInt16 s3 = (UInt16)~s2;
                    // 乘上-1和比例尺
                    _Speed = -(s3 * 0.1f);
                // 当待解析的数据为正数时
                    // 去掉最高位获取数据
                    UInt16 s = (UInt16)(((data[4] & 0x07) << 7) + (UInt16)((data[5] >> 1) & 0x7F));
                    // 乘上比例尺
                    _Speed = s * 0.1f;

1._Speed参数的占位情况。

76543210
data[4]F_Speed_Speed_Speed_Speed
data[5]_Speed_Speed_Speed_Speed_Speed_Speed_Speed

其中data[4]的第3位为我们符号位,也就是F_Speed。当我们做有符号码转换时,可以直接忽略,因为他不影响我们真实值的改变。

2.空位补全缘由

当我们使用更大的空间来做容器填充数据时,负数的空位补全。

UInt16也就等于2个字节

第0步运算之后,我们数据如下图所示。

1514131211109876543210
_S_S_S_S_S_S_S_S_S_S

我们知道,上面的所有_S的数据都是元数据的补码,因为该数是负数,所以我们需要将这个数据的符号位置为1,其它未使用的位(14、13、12、11、10)也置为1。这样我们就可以通过-1再求反码得到负数的值了。

积跬步以至千里:) (:一阵没来由的风

C# 从补码中获取有符号数的实际数值原理计算机存储数据时,默认是存储数据的补码。有符号的数粗存在符号位(最高位)。这里就会提到原码、反码、补码的概念。原码:用符号位和数值表示带符号数,正数的符号位用“0”表示,负数的符号位用“1”表示,数值部分用二进制形式表示。反码:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反。补码:正数的补码与原码相同,负数的补码为对该数的原码除... 我们知道,计算机最终处理的都是0和1的二进制的据,二进制又分为有符号和无符号,今天就带你们详细了解一下。我会以代码为例子让各位更清晰的明白,所用语言为C#语言。 无符号 所谓无符号就是没有符号有正负之分,但是只有负数的时候才会有符号,所以无符号就是正。 无符号不用考虑正负,所以的每个二进制都是用来表示数值的。 下面请看代码: UInt16 decimals = 2767; string binary = Convert.ToString(decimals,2);
C#开发,收到下位机串口据(温度信息),可能是正也可能是负数,如何转换? 第一反应是想起书本上的理论,无符号表示范围是多少到多少,有符号的表示范围是多少到多少,这就把问题复杂化了, 别忘了uint类型: uint raw = (uint)(bytes[7] * 256 + bytes[8]); //本项目的实际情况,用两个byte表示问题字 int wd = (int)raw; 把一个用二进制形式表示,如果是正,原码就等于其二进制,如果是负数,最高位,也就是最左边的那一位变成1 把一个表示成二进制的时候注意,一定要比正常表示的二进制多4位,用来标记是正还是负数 比如:12可以表示成1100,但是写的时候要比它多四位,也就是 0000 1100,最高位为0,表示为正,如果是-12,就是1000 1100 25可以表示成0001...