C# 从补码中获取有符号数的实际数值

原理

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

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

原码:用符号位和数值表示带符号数,正数的符号位用“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);
}
// 当待解析的数据为正数时
else
{
// 去掉最高位获取数据
UInt16 s = (UInt16)(((data[4] & 0x07) << 7) + (UInt16)((data[5] >> 1) & 0x7F)); // 乘上比例尺
_Speed = s * 0.1f;
}

图表解释

1._Speed参数的占位情况。

7 6 5 4 3 2 1 0

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步运算之后,我们数据如下图所示。

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

_S _S _S _S _S _S _S _S _S _S

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

版权声明:本文为CSDN博主「一阵没来由的风」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/YouyoMei/article/details/105880627

C# 从补码中获取有符号数的实际数值的更多相关文章

  1. 深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字

    上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言 ...

  2. verilog中的有符号数运算

    verilog中的有符号数运算 http://hi.baidu.com/lixu1113/item/d00dc095f86aed48f142159a verilog中的有符号数运算 有符号数的计算:若 ...

  3. verilog中的有符号数理解(转)

    verilog中的有符号数运算 有符号数的计算:若有需要关于有号数的计算,应当利用Verilog 2001所提供的signed及$signed()机制. Ex: input  signed [7:0] ...

  4. Android中获取TextView行数

    项目中发现,如果直接通过TextView.getLineCount()方法获取行数时,总是0,研究发现,setText()后立即调用getLineCount(), 这时TextView还未完成meas ...

  5. layui中从内置的分页中获取总记录数(转)

    封装的工具类: https://blog.csdn.net/QYHuiiQ/article/details/82147537

  6. Verilog有符号数处理

    内容主要摘自以下两个链接:  https://www.cnblogs.com/LJWJL/p/3481995.html  https://www.cnblogs.com/LJWJL/p/3481807 ...

  7. 关于有符号数和无符号数的转换 - C/C++

    转载自:http://www.94cto.com/index/Article/content/id/59973.html 1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题, ...

  8. 从Linux内核中获取真随机数【转】

    转自:http://www.cnblogs.com/bigship/archive/2010/04/04/1704228.html 内核随机数产生器 Linux内核实现了一个随机数产生器,从理论上说这 ...

  9. oracle 与sql serve 获取随机行数的数据

    Oracle 随机获取N条数据    当我们获取数据时,可能会有这样的需求,即每次从表中获取数据时,是随机获取一定的记录,而不是每次都获取一样的数据,这时我们可以采取Oracle内部一些函数,来达到这 ...

随机推荐

  1. 【多线程】线程礼让 Thread.yield()

    线程礼让 Thread.yield() 礼让线程,让当前正在执行的线程暂停,但不阻塞 : 将线程从运行状态转为就绪状态 : 让cpu重新调度,礼让不一定成功!看CPU心情. 代码示例: /** * @ ...

  2. 无线:PIN码

    PIN码(PIN1),全称Personal Identification Number.就是SIM卡的个人识别密码.手机的PIN码是保护SIM卡的一种安全措施,防止别人盗用SIM卡,如果启用了开机PI ...

  3. shellcode编写

    shellcode编写 shellcode是一段用于利用软件漏洞而执行的代码,通常使用机器语言编写,其目的往往是让攻击者获得目标机器的命令行shell而得名,其他有类似功能的代码也可以称为shellc ...

  4. mysql刷题笔记

    近期,为提升自己的工程能力,在休息时常通过刷题来回顾一下基础性知识. 于是选择了牛客网上的mysql知识题库练手,过程中,主要遇到了几个比较有意思的题,记录下来,方便回顾. 题1:SQL29 计算用户 ...

  5. 面试突击54:MySQL 常用引擎有哪些?

    MySQL 有很多存储引擎(也叫数据引擎),所谓的存储引擎是指用于存储.处理和保护数据的核心服务.也就是存储引擎是数据库的底层软件组织.在 MySQL 中可以使用"show engines& ...

  6. 使用pip安装库或执行pip命令时报错解决方案

    初次安装pip后执行安装升级一般不会有问题,但是国外的镜像源下载升级由于网速过慢会进行报错,提示需要升级 pip 或者下载速度很慢最后直接报了错如下图: 这个时候只需要修改镜像源即可,建议修改为永久镜 ...

  7. WAVE音频格式及及转换代码

    音频信号的读写.播放及录音 python已经支持WAV格式的书写,而实时的声音输入输出需要安装pyAudio(http://people.csail.mit.edu/hubert/pyaudio).最 ...

  8. 引入gitlab仓库代码到npm包的教程

    背景介绍 随着人类地发展,社会地进步,计算机技术地更新迭代,每一片码海里都有它宝贵的财富,每一座码山里都有着各自的秘密.怎么守住财富,隐藏一些秘密,成了一些开发人员所关心的事情. 需求分析 简单地说, ...

  9. SAP 文本框多行输入

    REPORT zjw_test01. CONSTANTS: gc_text_line_length TYPE i VALUE 72. TYPES: text_table_type(gc_text_li ...

  10. fiddle如何使用代理

    前言 Fiddle作为抓包工具深受程序员的喜爱,可能在代理方面有些会感觉到迷惑的,可以通过本文的学习来掌握一些基本的知识. Fiddle介绍 Fiddler是位于客户端和服务器端的HTTP代理,也是目 ...