Java 8位二进制加法
有人能解释一下如何用8位二进制加法计算校验和吗?这是文档的摘录: 这是消息的一般形式:Java 8位二进制加法,java,algorithm,delphi,binary,checksum,Java,Algorithm,Delphi,Binary,Checksum,有人能解释一下如何用8位二进制加法计算校验和吗?这是文档的摘录: 这是消息的一般形式: STX | TYPE | FS | DATA | FS | CHK | ETX STX是十六进制02 ETX是十六进制03 FS是十六进制15 “类型”是唯一的1字节消息标识符(例如,“p”表示轮询消息)。 “数据”包含可打印的ASCII字符 校验和 校验和是对和之间的所有字符(包括所有字符)计算的校验和是通过将所有包含的字符进行8位二进制相加,并假定第8位或奇偶校验位为零来计算的。超出第8位的进位丢失。8
STX | TYPE | FS | DATA | FS | CHK | ETX
STX是十六进制02
ETX是十六进制03
FS是十六进制15
“类型”是唯一的1字节消息标识符(例如,“p”表示轮询消息)。
“数据”包含可打印的ASCII字符
校验和
校验和是对
和
之间的所有字符(包括所有
字符)计算的校验和是通过将所有包含的字符进行8位二进制相加,并假定第8位或奇偶校验位为零来计算的。超出第8位的进位丢失。8位结果转换为两个可打印的ASCII十六进制字符,范围从00到FF,然后作为
插入数据流。十六进制字符A-F为大写。接收设备重新计算缓冲消息的校验和,并将其与接收到的校验和进行比较。比较是传输的后续确认(
)或否定确认(
)的基础。将每个字符视为一个整数值。由于每个字符的高位都假定为零(因为在规范中没有说明需要检查它),因此使用类似以下内容(pseudo-C/C++/Java/which)屏蔽其值:
现在您只需添加(pseudo-C/C++/Java/where):
这将连续添加每个ASCII字符,并从结果和中删除超过第8位的所有内容。当您全部完成(C或编写糟糕的C++)时:
作为一种优化(如果您真的需要它——在这种情况下不太可能!),您可以推迟s&=0xff
位,而是在校验和的使用点使用截断。不过,这不会为您节省太多性能,因为I/O的成本会高得多,并且可能会导致您在以后重构代码时忘记执行此操作。这类(未经测试的)JavaScript函数解决了您的问题吗?函数计算校验和(数据){
function calc_checksum( DATA ) {
var i;
var checksum = 0;
for ( i = 0; i < DATA.length; ++i ) {
checksum += DATA[i]; // any carry just falls off the high-order end
}
return 0x7F & checksum;
}
var i;
var校验和=0;
对于(i=0;i
在Java中,您可以执行以下操作
byte[] bytes =
byte total = 0;
for(byte b: bytes) total += b;
OutputStream os =
os.write(total);
此外,请使用以下功能
function Summatory(const Data: AnsiString): Byte;
var
C: AnsiChar;
begin
Result := 0;
for C in Data do
begin
Result := Result + Ord(C);
end;
end;
对于Delphi的旧版本,没有“For in”:
函数summary被声明为Byte,因此它将“忽略”超过第8位的进位。您可以传递所有要添加的字节
使用SysUtils
中的函数IntToHex
将8位结果转换为两个可打印的ASCII十六进制字符
例如:
ChkSum:=IntToHex(总和(数据),2)代码>当字节之和超过256时,上述答案均无效
OP可能试图将西门子Dimension EXL200化学分析仪与他的实验室信息系统连接起来
他发布的段落(关于校验和的规范)是从他们的手册中复制/粘贴的。
在过去的12个小时里,我一直在为这个特殊的问题绞尽脑汁,却找不到任何解决办法。
我包括西门子手册中提到的一些字符串,因为它们提供了校验和
您会注意到上面的所有答案都有效,但仅适用于部分字符串。
在其他情况下,手册中的校验和与我们使用上述方法得到的完全不同
我发布了两个例子,一个失败,一个成功=>相同的算法
为方便起见(由于协议使用十六进制字符,我将包含实际的字节数组,因此任何阅读此协议的人都可以使用自己选择的语言进行尝试)。
我希望有人能在这里找到解决方案:
示例一:@Just My Correct Opinion的解决方案失败:
/***
原始字符串:
P9300110
字节数组:
{80, 28, 57, 51, 48, 48, 28, 49, 28, 49, 28, 48, 28}
预期校验和:
6C
实际校验和:
3A
代码如下:
***/
字节[]byteArry={80,28,57,51,48,48,28,49,28,48,28};
字符串ss=新字符串(byteArry);
int s=0;
对于(int i=0;i
例二:@Just My Correct Opinion的解决方案成功:
/***
原始字符串:
文科硕士
字节数组:
{77, 28, 65, 28, 28}
预期校验和:
E2
实际校验和:
E2
代码如下:
***/
字节[]byteArry={77,28,65,28,28};
字符串ss=新字符串(byteArry);
int s=0;
对于(int i=0;i
在上面的例子中,我注意到只要字节的总和超过某个值(我不能确定),它就会失败,但我认为大约是256。任何高于256的结果都不同于西门子员工想要的结果。
第一个例子以很大的差距超过了256,但第二个例子是226。手册中还有一个更小字节和的例子,上面的代码似乎可以工作,生成预期的校验和。
我不是一个很好的程序员,但我确信这与溢出有关
巴尔加夫R.对我来说似乎很清楚。你不明白什么?你能给我举个例子(示例代码)吗?从来没有做过这样的事情…你需要在Delphi或Java中使用它吗?没关系,虽然这是在Delphi中,但我知道这两种语言。我认为OP是在寻找8位校验和,而不是7位校验和。Delphi示例代码+1-你应该使用(const Data:AnsiString)作为参数,但其余的都可以。对于旧版本的Delphi,没有“in”,您应该添加一个i局部变量,然后为i添加一个i局部变量
function calc_checksum( DATA ) {
var i;
var checksum = 0;
for ( i = 0; i < DATA.length; ++i ) {
checksum += DATA[i]; // any carry just falls off the high-order end
}
return 0x7F & checksum;
}
byte[] bytes =
byte total = 0;
for(byte b: bytes) total += b;
OutputStream os =
os.write(total);
function Summatory(const Data: AnsiString): Byte;
var
C: AnsiChar;
begin
Result := 0;
for C in Data do
begin
Result := Result + Ord(C);
end;
end;
function Summatory(const Data: AnsiString): Byte;
var
I: Integer;
begin
Result := 0;
for I := 1 to Length(Data) do
begin
Result := Result + Ord(Data[I]);
end;
end;
/***
RAW STRING:
P<FS>9300<FS>1<FS>1<FS>0<FS>
BYTE ARRAY:
{80, 28, 57, 51, 48, 48, 28, 49, 28, 49, 28, 48, 28}
EXPECTED CHECKSUM :
6C
ACTUAL CHECKSUM :
3A
CODE TO REPRODUCE BELOW:
***/
byte[] byteArry = {80, 28, 57, 51, 48, 48, 28, 49, 28, 49, 28, 48, 28};
String ss = new String(byteArry);
int s = 0;
for(int i = 0; i < ss.length(); i++)
{
s += ss.charAt(i) & 0x7f;
s &= 0xff;
}
System.out.println(s);
System.out.format("Checksum: %02X\n", s);
}
/***
RAW STRING:
M<FS>A<FS><FS>
BYTE ARRAY:
{77, 28, 65, 28, 28}
EXPECTED CHECKSUM :
E2
ACTUAL CHECKSUM :
E2
CODE TO REPRODUCE BELOW:
***/
byte[] byteArry = {77, 28, 65, 28, 28};
String ss = new String(byteArry);
int s = 0;
for(int i = 0; i < ss.length(); i++)
{
s += ss.charAt(i) & 0x7f;
s &= 0xff;
}
System.out.println(s);
System.out.format("Checksum: %02X\n", s);
}