如何将负二进制数转换为 int?
How can I convert negative binary number to int?
我想通过节点红色 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
谢谢
首先,在函数节点中创建新的 msg
对象是非常糟糕的做法,您应该只更新 msg.payload
值并传递原始对象。
下一步最简单的方法是使用缓冲区
例如
var b = Buffer(4)
b.writeUInt32BE(msg.playload)
msg.payload = b.readInt32BE()
return msg;
手动模式下的连接节点可以将 2 个较小的缓冲区合并为 16 位长度中的一个。
parseInt
将可变长度字符串作为输入,这意味着它无法将最高有效位识别为符号位。换句话说:它像十进制字符串一样解析二进制字符串,使用 -
作为符号;所以你必须使用不同于 parseInt
.
的方法
是什么阻碍了您采用该 16 位值并将其作为无符号传递?您只需要检查进入 javascript 的值是否大于 32767,然后手动进行二次补码转换:
你的传入数字范围将是 0..20000 正数 "originals" 和 45536..65535 原始范围 -20000..-1(如果我现在认为正确,我没有'验证)。这意味着转换很容易:
if( number > 32767 ) {
number = -65536 + number;
}
或者,对于任何二进制数字类型(小于您正在使用的语言的数字大小):
if( number > SIGNED_MAX_INT ) {
number = -(UNSIGNED_MAX_INT+1) + number;
}
(那些常量并不像写的那样存在,它们更像是伪代码)
嗯,JavaScript 在这一点上是蹩脚的,因为它没有强类型来做到这一点。可能不是最好的,但其中一种方法是创建自定义 Int
class。
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}
这可能会发展成更高级的东西,也可以在浏览器中使用。
我想通过节点红色 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
谢谢
首先,在函数节点中创建新的 msg
对象是非常糟糕的做法,您应该只更新 msg.payload
值并传递原始对象。
下一步最简单的方法是使用缓冲区
例如
var b = Buffer(4)
b.writeUInt32BE(msg.playload)
msg.payload = b.readInt32BE()
return msg;
手动模式下的连接节点可以将 2 个较小的缓冲区合并为 16 位长度中的一个。
parseInt
将可变长度字符串作为输入,这意味着它无法将最高有效位识别为符号位。换句话说:它像十进制字符串一样解析二进制字符串,使用 -
作为符号;所以你必须使用不同于 parseInt
.
是什么阻碍了您采用该 16 位值并将其作为无符号传递?您只需要检查进入 javascript 的值是否大于 32767,然后手动进行二次补码转换:
你的传入数字范围将是 0..20000 正数 "originals" 和 45536..65535 原始范围 -20000..-1(如果我现在认为正确,我没有'验证)。这意味着转换很容易:
if( number > 32767 ) {
number = -65536 + number;
}
或者,对于任何二进制数字类型(小于您正在使用的语言的数字大小):
if( number > SIGNED_MAX_INT ) {
number = -(UNSIGNED_MAX_INT+1) + number;
}
(那些常量并不像写的那样存在,它们更像是伪代码)
嗯,JavaScript 在这一点上是蹩脚的,因为它没有强类型来做到这一点。可能不是最好的,但其中一种方法是创建自定义 Int
class。
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}
这可能会发展成更高级的东西,也可以在浏览器中使用。