正如@harold所提到的,這不應該是一個問題:由於對數只是爲正數定義的,因此符號位始終爲零(請參閱相應的Wikipedia article)。因此,在linked answer該算法可直接移植到的Fortran(2008標準):
module mod_test
contains
function ilog2_b(val) result(res)
integer, intent(in) :: val
integer :: res
integer :: tmp
res = -1
! Negativ values not allowed
if (val < 1) return
tmp = val
do while (tmp > 0)
res = res + 1
tmp = shiftr(tmp, 1)
enddo
end function
end module
program test
use mod_test
print *,'Bitshifting: ', ilog2_b(12345)
print *,'Formula: ', floor(log(real(12345))/log(2.))
end program
這是基於所述的Fortran 95內BTEST
的溶液通過@agentp的建議:
module mod_test
contains
function ilog2_b2(val) result(res)
integer, intent(in) :: val
integer :: res
integer :: i
res = -1
! Negativ values not allowed
if (val < 1) return
do i=bit_size(val)-1,0,-1
if (btest(val, i)) then
res = i
return
endif
enddo
end function
end module
program test
use mod_test
print *,'Testing bits:', ilog2_b2(123456)
print *,'Formula: ', floor(log(real(123456))/log(2.))
end program
感謝@IanH指向bit_size
... 如果您的編譯器支持shiftr
,我會使用第一個變體。
@IanH提到尚未使用leadz
另一種方法,這是一個Fortran 2008功能:
module mod_test
contains
function ilog2_b3(val) result(res)
integer, intent(in) :: val
integer :: res
res = -1
! Negativ values not allowed
if (val < 1) return
res = bit_size(val)-leadz(val)-1
end function
end module
program test
use mod_test
print *,'Testing bits:', ilog2_b3(123456)
print *,'Formula: ', floor(log(real(123456))/log(2.))
end program
在非負操作數RSHIFT相當於一個邏輯右移,所以不看任何問題 – harold
看看標準函數'ILEN',它應該非常接近你所需要的(+/- 1)。 – njuffa
@njuffa這是HPF內在的,而不是Fortran呢?所以它可能得不到廣泛的支持。 – francescalus