简单的问题。我正在将一些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))
这是对的吗?
答案 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