如何将负二进制数转换为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 位数字? [复制]