在fortran的下一个2的力量

时间:2016-02-11 05:49:00

标签: fortran bitwise-operators fortran90 fortran77

简单的问题。我正在将一些C ++转换为fortran,并且无法弄清楚如何获得下一个这样的权力:

inline int
pow2roundup (int x)
{
    if (x == 0)
        ++x;
    --x;
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return x+1;
}

我试着这样做:

INTEGER :: x

IF (x == 0) x = x+1
x = x-1
x = x OR RSHIFT(x, 1)
x = x OR RSHIFT(x, 2)
x = x OR RSHIFT(x, 4)
x = x OR RSHIFT(x, 8)
x = x OR RSHIFT(x, 16)
x = x+1

但它不喜欢这些线条。我不认为按位OR运算符可以像这样使用。这里的一些帮助将不胜感激。

编辑:我想我可能已经想到这一点,但我不是百分百肯定。请看下面 - 那些OR行应该编辑成像这样使用IOR吗?

x = IOR(x,RSHIFT(x, 1))
x = IOR(x,RSHIFT(x, 2))
x = IOR(x,RSHIFT(x, 4))
x = IOR(x,RSHIFT(x, 8))
x = IOR(x,RSHIFT(x, 16))

这是对的吗?

4 个答案:

答案 0 :(得分:2)

OK, I'm now back at the ice fortress with access to a Fortran compiler so here's an answer to replace my earlier comment.

As you seem to have figured out the Fortran operator .grid-lines div { background: linear-gradient(0deg, #900 0, transparent 2px), linear-gradient(0deg, #bbf 0, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 100%); background-origin: padding-box; background-clip: border-box; position: absolute; top: 0; bottom: 0; width: 100px; } (the points are significant) operates on variables of type .or.. The intrinsic function logical does a bitwise inclusive ior on integer operands which it treats as bit vectors. I haven't tested your code but it looks OK.

However you seem to have taken the old adage that A real programmer can write Fortran in any language and turned it on its head to A real programmer can write any language in Fortran. I mean, what you have written is correct (if it is correct that is, I really mean that it seems to be a correct term-by-term translation of the C++ into the nearest equivalent Fortran) but it's not what a Fortran programmer would write. (Sure, other Fortran programmers are welcome to disagree on this.)

If I (a representative Fortran programmer) was working on a machine with an implementation of binary floating-point arithmetic I'd use the intrinsic function or for finding the next power of 2 greater than a given number. Like this:

exponent

which will write the next power of 2 greater than integer :: given_number ... write(*,*) exponent(real(given_number)) . If given_number is itself a power of 2 this will give the next power of 2. And take a little care at the end of the range of the kind of integer you are using.

答案 1 :(得分:0)

你是完全正确的。 以下可能是最快的方法。 (假设你想要2的准确权力上升 到下一个确切的2的力量。)

pure integer  function shift_up(x_in)
    integer, intent(in)::x_in
    integer::x
    x=x_in
    x = ior(x,rshift(x, 1))
    x = ior(x,rshift(x, 2))
    x = ior(x,rshift(x, 4))
    x = ior(x,rshift(x, 8))
    x = ior(x,rshift(x, 16))
    x = ior(x,rshift(x, 32))
    x= x + 1
    shift_up = x
 end function shift_up

使用log base 2(如下所示)需要大约14倍。

pure integer  function shift_logs(x_in)
    integer, intent(in)::x_in
    real ::x
    x = x_in
    shift_logs = 2**(floor(log(x)/log(2.0))+1)
end function shift_logs

答案 2 :(得分:0)

我知道这个话题有点陈旧,但我想补充一个我认为最直接和最惯用的答案:

ibits(0, (bit_size(n) - leadz(n))

所有这些都是用于整数位操作的 instrinsic 函数。此外,如果n本身是2的幂,它将返回下一个幂。

bit_size(n)给出n整数模型中的位数。如果参数的类型为integer(kind=int16),则返回16。

leadz(n)计算一个数字的前导零位数。例如。 leadz(19) == 11,因为19 == B'0000_0000_0001_0011'

ibits(i, pos)将1设置为数字pos上位置i的位(从右到左,从零开始)。因此,ibits(0, 16-11) == 32,因为32 == B'0000_0000_0010_0000'

P.D。:如果n > huge(n) / 2,应该小心。 Fortran没有无符号整数,因此如果设置了整数的第一位,则为负数。例如,对于16位,最大可表示的正数为2 ** 15 - 1 == 32767 == B'0111_1111_1111_1111'。鉴于B'1000_0000_0000_0000' == -32768,在16384之后没有下一个2的幂。

答案 3 :(得分:0)

您可以用这种方式为2的下一个幂编写fortran代码。例如,如果我们提供数字7,则将得到8(2^3)。如果我们提供9,它将给出16(2^4)

program power2
    implicit none
    integer::num,output

    integer::i,nmin,nmax
    integer,parameter:: N =3
    num = 17
    nmin = 1
    nmax = 2
    do i=1,N       !! N checkes the range (2^N)
        if  (num>nmin .and. num<=nmax) then
            output=nmax

        end if
        nmin = nmin*2
        nmax = nmax*2
    end do
    write(*,*)"num,output_value",num,output
end program