我在Fortran中有一个大型数组:
real, dimension(N) :: arr
我需要在程序的不同运行时检查数组是否完全相同。为此,我想创建要比较的数组的校验和。但是,我不知道要实现哪种算法。我查看了Flether和Adler的算法,但是在阅读我发现的示例中提供的C语法时遇到了问题。而且,我不知道如何使用Reals而不是字符/整数来实现它们。
在C实现中,我发现它们返回:
return (b << 16) | a;
但我不知道如何在Fortran中实现b << 16
部分,或者如果这很好地转化为实数。
答案 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