计算Fortran中真实数组的校验和

时间:2018-04-20 14:30:53

标签: hash fortran checksum

我在Fortran中有一个大型数组:

real, dimension(N) :: arr

我需要在程序的不同运行时检查数组是否完全相同。为此,我想创建要比较的数组的校验和。但是,我不知道要实现哪种算法。我查看了Flether和Adler的算法,但是在阅读我发现的示例中提供的C语法时遇到了问题。而且,我不知道如何使用Reals而不是字符/整数来实现它们。

在C实现中,我发现它们返回:

return (b << 16) | a;

但我不知道如何在Fortran中实现b << 16部分,或者如果这很好地转化为实数。

2 个答案:

答案 0 :(得分:1)

我终于通过在Fortran中实现Adler-32解决了这个问题:

subroutine test_hash(var)
  implicit none
  real, dimension(N), intent(in) :: var
  integer, dimension(N) :: int_var
  integer :: a=1, b=0, i=1, mod_adler=65521, hash = 0

  int_var = TRANSFER(var, a, nijk)

  do i= 1, NIJK
    a = MOD(a + int_var(i), mod_adler)
    b = MOD(b+a, mod_adler)
  end do

  hash = ior(b * 65536, a)

  print*, hash

end subroutine test_hash

我最终使用Fortran内部Transfer函数将32位实数转换为32位整数,因为这是算法所依赖的。在此之后我执行标准循环。使用@VladimirF建议的IOR函数,并将@ {ja72描述的b<<16表示为b * 65536。 最后,我能够将哈希值打印到控制台。

以这种方式实现它的原因是因为它使用起来比打开文件更快,计算每个文件的校验和。造成这种情况的主要原因是因为我需要经常检查哪个开关,因为我只是将它用于调试目的。

答案 1 :(得分:0)

经过修改的Lars无需大型临时阵列即可完成相同任务。另外,在Fortran中,在声明时初始化变量将意味着具有“保存”属性,在这种情况下,这是不希望的。

    function hash_real_asz(var,size_var) result(hash)
      implicit none
      integer(8) :: hash
      real(8), dimension(*), intent(in) :: var
      integer, intent(in) :: size_var
      integer(4) :: a,b,i,j
      integer(4), parameter :: mod_adler = 65521
      integer(4), allocatable :: tmp(:)

      a = 1
      b = 0

      do i= 1, size_var
        tmp = transfer(var(i), [0]) ! tmp will be an integer array sufficient to hold var(i)
        do j = 1,size(tmp)
            a = MOD(a+tmp(j), mod_adler) 
            b = MOD(b+a, mod_adler)
        end do
      end do

      hash = ior(b * 65536, a)

    end function