|
@@ -1,6 +1,7 @@
|
|
# 在`javaScript`中进制转换
|
|
# 在`javaScript`中进制转换
|
|
## 1. 前言
|
|
## 1. 前言
|
|
1. **问题描述**
|
|
1. **问题描述**
|
|
|
|
+
|
|
  在某次使用js操作`innfos`机器人时,使用`udp`进行连接后需要发送机械臂位置实现位置控制,`innfos`使用16进制编码进行通信.数据需要转换为32位进行发送。
|
|
  在某次使用js操作`innfos`机器人时,使用`udp`进行连接后需要发送机械臂位置实现位置控制,`innfos`使用16进制编码进行通信.数据需要转换为32位进行发送。
|
|
  初始方案使用js自带的函数进行类型转换,将计算结果直接进行`toString`操作,传入参数`16`告诉转换为16进制值,直接使用`toString`函数转换成的`hex`进制字符串会出现一些问题.印象比较深刻的问题是转换数值小于16的值时会出现首字为0情况下自动忽略0. 需要手动在前方进行添加 0
|
|
  初始方案使用js自带的函数进行类型转换,将计算结果直接进行`toString`操作,传入参数`16`告诉转换为16进制值,直接使用`toString`函数转换成的`hex`进制字符串会出现一些问题.印象比较深刻的问题是转换数值小于16的值时会出现首字为0情况下自动忽略0. 需要手动在前方进行添加 0
|
|
|
|
|
|
@@ -18,17 +19,25 @@
|
|
```
|
|
```
|
|
|
|
|
|
2. **解决思路**
|
|
2. **解决思路**
|
|
|
|
+
|
|
  首先得清楚为什么会这样,在js中使用的是有32位符号数,当时我用`win`计算器应该是64位的,找出了一些规律.但是我要通信的对象使用的是32位无符号数,尝试使用`win`的计算器生成的16进制值发送是可行的.于是问题变为了在js中如何生成32位无符号16进制数了.
|
|
  首先得清楚为什么会这样,在js中使用的是有32位符号数,当时我用`win`计算器应该是64位的,找出了一些规律.但是我要通信的对象使用的是32位无符号数,尝试使用`win`的计算器生成的16进制值发送是可行的.于是问题变为了在js中如何生成32位无符号16进制数了.
|
|
> [!tip]
|
|
> [!tip]
|
|
> 此处需要了解一下 [计算机补码@张子秋](https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html) ,从搜索引擎直接搜索的看着有点蒙逼,这个博文的看着要稍微舒服一点. 字体清晰一点
|
|
> 此处需要了解一下 [计算机补码@张子秋](https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html) ,从搜索引擎直接搜索的看着有点蒙逼,这个博文的看着要稍微舒服一点. 字体清晰一点
|
|
|
|
+> 也可以参考一下,如果可以的话 [无符号数wiki](https://zh.wikipedia.org/wiki/%E6%97%A0%E7%AC%A6%E5%8F%B7%E6%95%B0)
|
|
|
|
|
|
  根据我的粗俗理解,缝合一下理论就是,无符号数将会在数据前面用一位来专门表示正数还是负数.所以`n`位的无符号数能表示的最大正整数值`y`为
|
|
  根据我的粗俗理解,缝合一下理论就是,无符号数将会在数据前面用一位来专门表示正数还是负数.所以`n`位的无符号数能表示的最大正整数值`y`为
|
|
$y=2^n/2-1$
|
|
$y=2^n/2-1$
|
|
根据该公式发现无符号数的最大值只有位数的一半还要少1。有一半空间用来存储负整数。比如16位有符号数,可以表示`-32768~32767`之间的任意整数,如果是16位无符号数可以表示`0~65535`之间的整数。例如,在16位有符号数中,`0xFFFF`表示`-1`,但在16位无符号数中`0xFFFF`表示`65535`,可以依次获取-2,以及-3的值,发现可以使用目标位数的最大值来减去目标值来获取一个负数的16进制值。参考[无符号数wiki](https://zh.wikipedia.org/wiki/%E6%97%A0%E7%AC%A6%E5%8F%B7%E6%95%B0)
|
|
根据该公式发现无符号数的最大值只有位数的一半还要少1。有一半空间用来存储负整数。比如16位有符号数,可以表示`-32768~32767`之间的任意整数,如果是16位无符号数可以表示`0~65535`之间的整数。例如,在16位有符号数中,`0xFFFF`表示`-1`,但在16位无符号数中`0xFFFF`表示`65535`,可以依次获取-2,以及-3的值,发现可以使用目标位数的最大值来减去目标值来获取一个负数的16进制值。参考[无符号数wiki](https://zh.wikipedia.org/wiki/%E6%97%A0%E7%AC%A6%E5%8F%B7%E6%95%B0)
|
|
  那么:2的16次方为65536,最大的负整数数从-1开始.那么可以通过65536来加上负数来得到对应的无符号数的10进制值.
|
|
  那么:2的16次方为65536,最大的负整数数从-1开始.那么可以通过65536来加上负数来得到对应的无符号数的10进制值.
|
|
  例如:在16位有符号数中的-1,转换为16进制值. 65536+(-1) = 65535 将65535转换为16进制值可以得到 `0xFFFF`
|
|
  例如:在16位有符号数中的-1,转换为16进制值. 65536+(-1) = 65535 将65535转换为16进制值可以得到 `0xFFFF`
|
|
|
|
+
|
|
3. **具体代码**
|
|
3. **具体代码**
|
|
|
|
+
|
|
根据上方分析可以获取一个函数
|
|
根据上方分析可以获取一个函数
|
|
|
|
+> [!warning]
|
|
|
|
+> 代码将一步步来解决问题
|
|
|
|
+
|
|
|
|
+简单版本
|
|
<!-- tabs:start -->
|
|
<!-- tabs:start -->
|
|
#### **易读版本**
|
|
#### **易读版本**
|
|
|
|
|
|
@@ -52,3 +61,42 @@ function toHex(n,number){return (number<0?Math.pow(2,n)+number:number).toString(
|
|
```
|
|
```
|
|
|
|
|
|
<!-- tabs:end -->
|
|
<!-- tabs:end -->
|
|
|
|
+
|
|
|
|
+根据上方的代码可以在大部分情况下获得正确的16进制值,但是在某些场景下面则无法正常获取16进制值
|
|
|
|
+例如: 串口通信时会出现 `0f 0a ff` 之类的指令,但是根据上方生成的16进制值会自动忽略掉最前方的 0,比如值为1时需要01,
|
|
|
|
+
|
|
|
|
+将代码小小升级一下,前方自动补充0
|
|
|
|
+
|
|
|
|
+<!-- tabs:start -->
|
|
|
|
+#### **易读版本**
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+function toHex(n,number){
|
|
|
|
+ let hexStr,resultHex;
|
|
|
|
+ if(number<0){
|
|
|
|
+ // 如果是负数则获取指定位数n的最大位数的值(比可表示数的最大值还要多1),因为0不算是负数所以可以直接拿理论最大值去减
|
|
|
|
+ let tmpNumber = Math.pow(2,n) + number
|
|
|
|
+ hexStr = tmpNumber.toString(16)
|
|
|
|
+ }else{
|
|
|
|
+ // 如果当前数为正数则直接调用正常的转16进制逻辑
|
|
|
|
+ hexStr = number.toString(16)
|
|
|
|
+ }
|
|
|
|
+ //判断字符串长度是否能直接被2整除
|
|
|
|
+ if((hexStr.length%2)==1){
|
|
|
|
+ resultHex = '0' + hexStr;
|
|
|
|
+ }else{
|
|
|
|
+ // 如果获取到的16进制字符串长度正好可以将2整除,则表示前面的0没有被忽略
|
|
|
|
+ resultHex = hexStr;
|
|
|
|
+ }
|
|
|
|
+ return resultHex;
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+#### **爽就完事版本**
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+// 还是有变量啊......
|
|
|
|
+function toHex(n,number){let t =(number<0?Math.pow(2,n)+number:number).toString(16);return t.length%2?'0'+t:t}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+<!-- tabs:end -->
|