Perl 校验和计算迁移到 Java
Perl Checksum Calculation Migration to Java
我的任务是将 Perl 程序迁移到 java。
我遇到了一些麻烦,Perl 中有一个函数可以计算校验和
sub ComputeChecksum {
my ($val) = @_;
$value= 0;
$multiplier = 1;
$dlength=length($val);
for($i=0; $i<$dlength; $i++) {
$ival=ord(substr($val, $i, 1));
$ival*=$multiplier;
$value+=$ival/100000;
$value+=$ival%100000;
$multiplier%=2;
$multiplier++;
}
$value%=100000;
$value=(100000-$value)%100000;
return ($value);
}
我将这段代码翻译成 java 如下所示
private static long computeCheckSum(String id){
long value = 0;
long multiplier = 1;
int dlength = id.length();
for(int i=0; i< dlength; i++){
int ival = id.charAt(i);
ival *= multiplier;
value += ival/100000;
value += ival%100000;
multiplier %= 2;
multiplier++;
}
value %= 100000;
value = ((100000-value)%100000);
return value;
}
但是我 运行 在验证数据库中的旧数据时遇到了一个问题,大约 5% 的时间 java 中计算的校验和与之前由 Perl 计算的校验和不匹配, 它错过了 1.
以下是旧数据的一些示例以及 java
中的结果
Perl Java
ff08ccfba8ad417db2857fc8933788af:96410 / 96409
ff163b2b2e3ef18265d08cc8965b864d:96533 / 96532
ff3848ff301b534b609148af93b2c9ce:96626 / 96625
ff48ec78ea190f44233c9050fd73137d:96631 / 96630
ff62234601e28e6f5d7ff89d95afbec0:96424 / 96423
ff78f4cabe5a565a1cdf11f752f13654:96495 / 96494
ff89dc6b86a535ef265727af90a9b6b3:96596 / 96595
ff98337de5eb9e60f1db51dbd14a4dd2:96366 / 96365
fff76022c6f9f7794793141a9f2a00d2:96813 / 96812
在这些集合中,第一部分是数据库中的数据,由 uid、分号和 Perl 计算的校验和组成,这就是数据在数据库中的保存方式。
为了进行比较,我添加了斜线和我的 java 代码使用 uid 部分计算的结果。
任何人都可以指出正确的方向,说明为什么会发生这种情况吗?
我需要能够在 100% 的时间内计算出正确的校验和。
============================================= =========================
更新:
我更改了我的 java 代码,以 float 而不是 int 进行所有计算,结果更有趣,不同之处在于同一组 uid,而不是产生差异为 1,相差 2。
我正在考虑提议重新计算所有UID的校验和,并更新所有受影响的表。
为 ff08ccfba8ad417db2857fc8933788af
打印 $ival/100000
得到以下结果:
0.00102
0.00204
0.00048
0.00112
...
我不知道 Java 程序中的除法是否是整数除法,但无论如何都等于加零。这就是区别。
顺便说一句,我怀疑 Perl 程序是有问题的程序。我怀疑需要整数除法 (int($ival/100000)
),但不小心使用了浮点除法。
也就是说,对于您提供的数字,差异似乎不足以产生结果,即使用 int($ival/100000)
产生与 $ival/100000
相同的结果。显然还有另一个区别。
...或者有吗?添加
while (<DATA>) {
chomp;
say $_, ":", ComputeChecksum($_);
}
__DATA__
ff08ccfba8ad417db2857fc8933788af
ff163b2b2e3ef18265d08cc8965b864d
ff3848ff301b534b609148af93b2c9ce
ff48ec78ea190f44233c9050fd73137d
ff62234601e28e6f5d7ff89d95afbec0
ff78f4cabe5a565a1cdf11f752f13654
ff89dc6b86a535ef265727af90a9b6b3
ff98337de5eb9e60f1db51dbd14a4dd2
fff76022c6f9f7794793141a9f2a00d2
我明白你说的 Java 结果(即使 $ival/100000
):
ff08ccfba8ad417db2857fc8933788af:96409
ff163b2b2e3ef18265d08cc8965b864d:96532
ff3848ff301b534b609148af93b2c9ce:96625
ff48ec78ea190f44233c9050fd73137d:96630
ff62234601e28e6f5d7ff89d95afbec0:96423
ff78f4cabe5a565a1cdf11f752f13654:96494
ff89dc6b86a535ef265727af90a9b6b3:96595
ff98337de5eb9e60f1db51dbd14a4dd2:96365
fff76022c6f9f7794793141a9f2a00d2:96812
我的任务是将 Perl 程序迁移到 java。
我遇到了一些麻烦,Perl 中有一个函数可以计算校验和
sub ComputeChecksum {
my ($val) = @_;
$value= 0;
$multiplier = 1;
$dlength=length($val);
for($i=0; $i<$dlength; $i++) {
$ival=ord(substr($val, $i, 1));
$ival*=$multiplier;
$value+=$ival/100000;
$value+=$ival%100000;
$multiplier%=2;
$multiplier++;
}
$value%=100000;
$value=(100000-$value)%100000;
return ($value);
}
我将这段代码翻译成 java 如下所示
private static long computeCheckSum(String id){
long value = 0;
long multiplier = 1;
int dlength = id.length();
for(int i=0; i< dlength; i++){
int ival = id.charAt(i);
ival *= multiplier;
value += ival/100000;
value += ival%100000;
multiplier %= 2;
multiplier++;
}
value %= 100000;
value = ((100000-value)%100000);
return value;
}
但是我 运行 在验证数据库中的旧数据时遇到了一个问题,大约 5% 的时间 java 中计算的校验和与之前由 Perl 计算的校验和不匹配, 它错过了 1.
以下是旧数据的一些示例以及 java
中的结果 Perl Java
ff08ccfba8ad417db2857fc8933788af:96410 / 96409
ff163b2b2e3ef18265d08cc8965b864d:96533 / 96532
ff3848ff301b534b609148af93b2c9ce:96626 / 96625
ff48ec78ea190f44233c9050fd73137d:96631 / 96630
ff62234601e28e6f5d7ff89d95afbec0:96424 / 96423
ff78f4cabe5a565a1cdf11f752f13654:96495 / 96494
ff89dc6b86a535ef265727af90a9b6b3:96596 / 96595
ff98337de5eb9e60f1db51dbd14a4dd2:96366 / 96365
fff76022c6f9f7794793141a9f2a00d2:96813 / 96812
在这些集合中,第一部分是数据库中的数据,由 uid、分号和 Perl 计算的校验和组成,这就是数据在数据库中的保存方式。
为了进行比较,我添加了斜线和我的 java 代码使用 uid 部分计算的结果。
任何人都可以指出正确的方向,说明为什么会发生这种情况吗? 我需要能够在 100% 的时间内计算出正确的校验和。
============================================= =========================
更新:
我更改了我的 java 代码,以 float 而不是 int 进行所有计算,结果更有趣,不同之处在于同一组 uid,而不是产生差异为 1,相差 2。
我正在考虑提议重新计算所有UID的校验和,并更新所有受影响的表。
为 ff08ccfba8ad417db2857fc8933788af
打印 $ival/100000
得到以下结果:
0.00102
0.00204
0.00048
0.00112
...
我不知道 Java 程序中的除法是否是整数除法,但无论如何都等于加零。这就是区别。
顺便说一句,我怀疑 Perl 程序是有问题的程序。我怀疑需要整数除法 (int($ival/100000)
),但不小心使用了浮点除法。
也就是说,对于您提供的数字,差异似乎不足以产生结果,即使用 int($ival/100000)
产生与 $ival/100000
相同的结果。显然还有另一个区别。
...或者有吗?添加
while (<DATA>) {
chomp;
say $_, ":", ComputeChecksum($_);
}
__DATA__
ff08ccfba8ad417db2857fc8933788af
ff163b2b2e3ef18265d08cc8965b864d
ff3848ff301b534b609148af93b2c9ce
ff48ec78ea190f44233c9050fd73137d
ff62234601e28e6f5d7ff89d95afbec0
ff78f4cabe5a565a1cdf11f752f13654
ff89dc6b86a535ef265727af90a9b6b3
ff98337de5eb9e60f1db51dbd14a4dd2
fff76022c6f9f7794793141a9f2a00d2
我明白你说的 Java 结果(即使 $ival/100000
):
ff08ccfba8ad417db2857fc8933788af:96409
ff163b2b2e3ef18265d08cc8965b864d:96532
ff3848ff301b534b609148af93b2c9ce:96625
ff48ec78ea190f44233c9050fd73137d:96630
ff62234601e28e6f5d7ff89d95afbec0:96423
ff78f4cabe5a565a1cdf11f752f13654:96494
ff89dc6b86a535ef265727af90a9b6b3:96595
ff98337de5eb9e60f1db51dbd14a4dd2:96365
fff76022c6f9f7794793141a9f2a00d2:96812