Fortran判断整数是否为2的幂函数问题:代码在2^29时失效
判断整数是否为2的幂的正确Fortran实现
原代码的问题
原代码通过浮点对数运算判断结果是否为整数,依赖real(16)的精度和log函数的计算准确性。当整数超过2^28后,即便16位浮点数也无法完全精确表示所有更大整数,再加上对数运算的舍入误差累积,会导致fractional_part无法严格等于0,最终判断失效。这类整数属性判断场景,完全不适合用浮点运算实现。
正确的位运算实现
2的幂的二进制表示有且仅有一个二进制位为1,利用这个特性可以用位运算快速判断,彻底避免浮点误差:
elemental logical function is_power_of_two(n) integer, intent(in) :: n is_power_of_two = (n > 0) .and. (iand(n, n-1) == 0) end function is_power_of_two program test_pow2 implicit none logical :: is_power_of_two integer :: ii read(*,*) ii if (is_power_of_two(ii)) then write(*,*) ii, " is a power of two" else write(*,*) ii, " is NOT a power of two" end if end program test_pow2
原理说明
n > 0:排除0和负整数,因为2的幂都是正整数iand(n, n-1) == 0:当n是2的幂时,二进制形式为100...0,n-1则是011...1,二者按位与的结果必然为0;如果n不是2的幂,二进制至少有两个1,n-1只会翻转最后一个1及后面的位,按位与结果不为0
额外说明
如果需要处理更大范围的整数(比如64位整数),只需把函数中的integer类型改为integer(8)即可,位运算逻辑完全通用,且不存在精度限制问题。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

