Как мне обрабатывать логические выражения, применяемые к целочисленным значениям с помощью gfortran? - PullRequest
2 голосов
/ 07 января 2011

Я переписываю некоторый код для компиляции программы с помощью компилятора gfortran, а не компилятора ifort, который я обычно использую. Код следует:

_Subroutine SlideBits (WORD, BITS, ADDR) 

Implicit None  
Integer(4) WORD  
Integer(4) BITS  
Integer(4) ADDR  
Integer(4) ADDR1 

ADDR1 = 32 - ADDR  
WORD = (WORD .And. (.Not.ISHFT(1,ADDR1))) .Or. ISHFT(BITS,ADDR1)  

End_ 

Когда я компилирую приведенный выше код с использованием компилятора gfortran, я получаю эту ошибку:

WORD = (WORD .And. (.Not.ISHFT(1,ADDR1))) .Or. ISHFT(BITS,ADDR1) 

Error: Operand of .NOT. operator at (1) is INTEGER(4)  

Все три переменные, входящие в подпрограмму, являются целыми числами. Я немного осмотрелся, и вики gfortran утверждают, что компилятор gfortran должен уметь обрабатывать логические оценки, применяемые к целочисленным значениям. Несколько других сайтов, которые я посетил, либо цитируют gnu wiki, либо соглашаются с этим. Это первый раз, когда я вижу эту ошибку как компилятор Intel Fortran (ifort), который я обычно использую без компиляции.

Ответы [ 3 ]

3 голосов
/ 22 января 2014

Комментарии / ответы выше "могут. Не быть" правильными ответами, в зависимости от вашей конечной цели.

Вероятная цель этого утверждения "WORD = .." - .NOT. чтобы получить логический / логический результат, а получить некий целочисленный перечислитель.

Чтобы увидеть это, сначала «игнорируйте» сдвиг битов (iShift () и т. Д.) И просто посмотрите на что-то вроде IntR = Int1 .Or. Int2. Это приведет к «правильному» целочисленному результату. Значение будет зависеть не только от значений типа int, но также от их объявленного «типа» (например, Integer (1), Integer (2) и т. Д.)

То есть полученное значение WORD будет "правильным" целым числом; что-то вроде "33504" .. или что-то, (вероятно) .НЕТ. 0/1 или -1/0 или .True ./. False. и т.д.

Если вы замените = Int1. Или. Int2 с = (Int1 / = 0). Или (Int2 / = 0) ... вы получите "целочисленное логическое" (т. Е. 0/1 и т. Д.) И НЕ БУДЕТ производить желаемый счетчик ... если это то, что вы ищете.

.Or. на двух Int это своего рода побитовое сложение, которое создает новое число на основе того, как биты выравниваются / размер слова и т. д.

e.g. 3 == 011, 2 = 010 ... so, 3 .Or. 2 ==> 011 = 3
e.g. 3 == 011, 5 = 101 ... so, 3 .Or. 5 ==> 111 = 7
e.g. 5 == 101, 5 = 101 ... so, 5 .Or. 5 ==> 101 = 5

... аналогично .А. обеспечивает вид умножения.

Этот метод иногда используется для создания перечислителей, подобно использованию степеней двух (1,2,4,8 ...) для присвоения значения. Тогда любая сумма тех значения могут быть разложены, например, на составляющие его элементы. Например, если a (1) = 2 и a (2) = 8, то сумма 10 может быть разложена на показать выборы были 1-й и 4-й элементы (1,2,4,8, ...) и т. д.

Это может помочь концептуализировать это, отметив, что сдвиг битов подобен умножению на 2 (для сдвига влево) и делению на 2 (для сдвига вправо).

Кстати, вам не нужно ограничивать это Фортраном. Ударьте это в функцию VBA и посмотрите результат в вашей таблице VBA не имеют встроенные сдвиги битов, но они доступны ... в любом случае он будет демонстрировать Int1 .Or. Поведение Int2 даже без смещения битов, например

Function TwoIntsOr(Int1 As Long, Int2 As Long) As Long
    '
    TwoIntsOr = Int1 Or Int2
    '
End Function

- .Ор. в Фортране

Function TwoIntsOr(Int1, Int2)
    Integer     :: TwoInstOr
    Integer, Intent(In) :: Int1, Int2
    !
    TwoIntsOr = Int1 .Or. Int2
    !
End Function

).

2 голосов
/ 07 января 2011

Это не стандартный Фортран для применения логических / логических операторов к целочисленным переменным.Если целью является логический результат, идеальным решением будет преобразование типов в логические.Если, как показывает случайное исследование, код действительно выполняет побитовые операции, то было бы лучше использовать встроенные функции IAND и IOR.

0 голосов
/ 07 января 2011

gfortran ожидает логических значений для логических операторов, а код предоставляет целые числа. Используйте сравнения с нулем вместо логических операторов.

WORD = ((WORD /= 0) .And. (ISHFT(1,ADDR1) == 0)) .Or. (ISHFT(BITS,ADDR1) /= 0)

gfortran и ifort используют разные представления для значений .true. и .false., поэтому лучше придерживаться логических значений, когда это то, что нужно коду. При преобразовании из ifort в gfortran я получил бит от первого, представляющего .true. как -1, и второго, использующего 1 для той же цели, вместо традиционного (C-like) not 0.

...