如何将负二进制数转换为int?

Posted

技术标签:

【中文标题】如何将负二进制数转换为int?【英文标题】:How can I convert negative binary number to int? 【发布时间】:2020-08-29 16:15:09 【问题描述】:

我想通过节点红色 modbus 节点从数据源读取数据。范围是 -20000 到 20000,但是节点不能处理负数,所以我不得不将它们转换为二进制数(DWORD),将它们拆分为低位和高位字并将这些字转换回整数。

var low

function dec2bin(dec)
    return (dec >>> 0).toString(2);


var a = msg.payload

if (a >= 0)

    a = dec2bin(a);
    a = parseInt(a,2);

 else 

    a = dec2bin(a);
    a = a.substr(16);
    a = parseInt(a,2);

 

low =  payload: a ;

return low;

为了可视化,我想使用仪表板节点,但因此我需要将 2 个二进制字符串连接在一起并将它们转换为 int。

问题:

node red 将它们转换为 qword,因此二进制数 1111 1111 1111 1111 1111 1100 0001 1000 被视为 4.294.966.296,而不是 -1000。但如果我用 1 个石灰填充下一个剩余部分,那么:1111 1111 1111 1111 1111 1111 1111 1111 1111 1100 0001 1000 拿出 18446744073709552000

谢谢

【问题讨论】:

【参考方案1】:

parseInt 处理可变长度字符串作为输入,这意味着它无法将最高有效位识别为符号位。换句话说:它像十进制字符串一样解析二进制字符串,使用-作为符号;所以你必须使用与parseInt不同的方法。

是什么阻碍了您获取 16 位值并将其作为无符号传递?您只需要检查进入您的 javascript 的值是否大于 32767,然后手动进行二补码转换:

对于正“原件”,您的传入数字范围将是 0..20000,对于原始范围 -20000..-1,您的传入数字范围将是 45536..65535(如果我现在认为正确,我没有验证)。这意味着转换很容易:

if( number > 32767 ) 
  number = -65536 + number;

或者,对于任何二进制数字类型(小于您正在使用的语言的数字大小):

if( number > SIGNED_MAX_INT ) 
  number = -(UNSIGNED_MAX_INT+1) + number;

(那些常量并不像写的那样存在,它们更像是伪代码)

【讨论】:

【参考方案2】:

首先,在函数节点中创建新的msg 对象是非常糟糕的做法,您应该只更新msg.payload 值并传递原始对象。

接下来最简单的方法是使用缓冲区

例如

var b = Buffer(4)
b.writeUInt32BE(msg.playload)
msg.payload = b.readInt32BE()

return msg;

手动模式下的连接节点可以将 2 个较小的缓冲区组合成 16 位长度之一。

【讨论】:

好的,您的回答,您能告诉我为什么创建新对象是一种不好的做法吗?问题是,我有 2 个 uint16 值。如何将缓冲区合并为一个,以便我可以使用您的功能? 这里是高字节的例子:"data":[65535],"buffer":[0xff,0xff] 和低字节的例子:"data":[64536] ,"缓冲区":[0xfc,0x18] 好的,因为它已经是缓冲区,只需将它们合并到一个缓冲区中并使用提供的方法从中读取。您不会创建新的 msg,因为这会丢弃任何可能与有效负载一起传播的额外元数据,例如http-response 节点工作所需的 http-in 节点添加的 msg.resp 对象。 我无法将它们与连接节点合并,我必须以某种方式手动进行吗?你能告诉我怎么做吗?抱歉,我对 javascript 很陌生。 其实你可以将它们与join节点合并(假设它们总是按顺序到达)【参考方案3】:

好吧,JavaScript 在这一点上是蹩脚的,因为它没有强大的类型来做到这一点。可能不是最好的,但其中一种方法是创建自定义 Int 类。

class Int 
  constructor(length, binaryStr) 
    const cleanBinary = "0".repeat(length - binaryStr.length) + binaryStr
    if (cleanBinary.startsWith("1")) 
      const invertedBinary = cleanBinary.split("")
        .map(char => char === "1" ? "0": "1")
        .join("")
      this.decValue = -parseInt(invertedBinary, 2) - 1
     else 
      this.decValue = parseInt(cleanBinary, 2)
    
  

类似的东西

new Int(8, "11111100")
> Int decValue: -4
strBin = "11111111111111111111110000011000";
new Int(strBin.length, strBin)
> Int decValue: -1000

这可能会被开发成更高级的东西,也可以在浏览器中使用。

【讨论】:

我在将这个类实现成节点红色时遇到了一些问题。此外,我对 javascript 还是很陌生,所以将它转换为函数并不容易。我这里需要的是:strBin = msg.payload;新的 Int(strBin.length, strBin) msg​​.payload = Int;这不起作用,因为它是一个类。你有什么建议吗? 如果你有一个固定大小的数字,例如16位,你可以通过const convertedNumber = new Int(16, msg.playload).decValue这样的方式得到答案。但请注意,该类接受不带空格的二进制文件。您可以在之前添加一些格式。

以上是关于如何将负二进制数转换为int?的主要内容,如果未能解决你的问题,请参考以下文章

如何将表示二进制的 int 向量转换为表示十进制数的 int 向量? C++

sql Server如何编写函数实现把十进制数转换为二进制数?求大神相助!!

如何将 int 转换为十六进制数并将其打印为 c 中的 3 位数字? [复制]

python中二进制数10101转为十进制数的表达式是啥?

Python - 如何将 int 转换为表示 32 位十六进制数的字符串

C语言,如何把输入的一个字符串,转换为相应的二进制数?