Fortran实型大数组校验和计算方法咨询
验证Fortran实型数组一致性的校验和实现
首先,你不用纠结实型和字符/整型的差异——本质上所有数据在内存里都是字节序列,所以我们可以把实型数组直接当作连续的字节流来处理校验和算法,这样Fletcher或Adler的逻辑就和处理其他类型完全一致了。
下面分步骤给你讲清楚怎么实现:
核心思路:把实型数组转成字节序列
Fortran里可以用transfer函数,把你的实型数组转换成integer(1)(单字节整型)数组,这样就能遍历每个字节来计算校验和。比如:
real, dimension(N) :: arr integer(1), dimension(size(arr)*storage_size(arr)/8) :: byte_arr byte_arr = transfer(arr, byte_arr)
这里storage_size(arr)会返回每个实型元素的比特数,除以8就是字节数,这样byte_arr的长度刚好是整个实型数组的总字节数。
Fletcher校验和的Fortran实现
Fletcher的核心是计算两个累加和,其中第二个累加和是第一个累加和的累加。以常用的Fletcher-32为例(适合较长数据),实现如下:
function fletcher32(byte_arr) result(checksum) integer(1), intent(in) :: byte_arr(:) integer(4) :: checksum, sum1, sum2 integer :: i, len_arr len_arr = size(byte_arr) sum1 = 0 sum2 = 0 do i = 1, len_arr sum1 = mod(sum1 + int(byte_arr(i), 4), 65535) sum2 = mod(sum2 + sum1, 65535) end do checksum = ior(shiftl(sum2, 16), sum1) end function fletcher32
调用的时候,把上面生成的byte_arr传进去就行。如果需要Fletcher-16,只需要把模数改成255,最终校验和是ior(shiftl(sum2, 8), sum1)。
Adler-32校验和的Fortran实现
Adler-32是基于两个累加和,其中第一个是所有字节的和,第二个是第一个累加和的累加,并且使用固定的模数65521(一个质数),实现更简单:
function adler32(byte_arr) result(checksum) integer(1), intent(in) :: byte_arr(:) integer(4) :: checksum, a, b integer :: i, len_arr integer, parameter :: MOD_ADLER = 65521 len_arr = size(byte_arr) a = 1 b = 0 do i = 1, len_arr a = mod(a + int(byte_arr(i), 4), MOD_ADLER) b = mod(b + a, MOD_ADLER) end do checksum = ior(shiftl(b, 16), a) end function adler32
Adler-32的计算速度通常比Fletcher快,而且碰撞概率更低,更适合大型数组。
额外提示
- 如果你的数组非常大,担心计算时间,可以考虑分块计算,最后合并结果,不过对于大多数情况,直接遍历整个字节数组就足够了。
- 注意:如果你的程序在不同编译环境(比如不同编译器、不同字节序的机器)运行,实型的二进制表示可能不同,但你是验证同一程序的不同运行实例,所以这个问题不存在。
- 如果你只是需要快速验证,也可以用简单的统计量(比如数组所有元素的和、平方和),但这种方法的碰撞概率比专门的校验和算法高,适合初步验证,不适合严格校验。
内容的提问来源于stack exchange,提问作者Lars
相关产品推荐
相关产品推荐

