Битовые размеры целых чисел Фортрана - PullRequest
2 голосов
/ 12 февраля 2020

У меня есть следующая программа, чтобы привести минимальный пример, который я не понимаю ни о битовом представлении вообще, ни в Fortran. Если я компилирую с gfortran 7.5 или ifort 18.0, он пропускает все утверждения, и я не понимаю, почему.

Функция popcnt возвращает количество установленных бит ('1' бит) в двоичном представлении I.

В моем понимании знак целого числа со знаком кодируется в один бит, поэтому, если I go от popcnt(n) до popcnt(-n), он должен измениться на единицу. Если я могу express n как степень 2, он должен иметь popcnt 1 или 2 (в зависимости от знака.) В чем моя ошибка в мышлении?

program bit_sizes
    use iso_fortran_env, only: int64
    implicit none
    integer(int64), parameter :: n = -4294967296_int64

    call assert(2_int64 ** 32_int64 == -n)
    call assert(popcnt(-n) == 1)
    call assert(popcnt(n) == 32)

contains

    subroutine assert(cond)
        logical, intent(in) :: cond
        if (.not. cond) error stop
    end subroutine
end program


Ответы [ 2 ]

3 голосов
/ 13 февраля 2020

Ошибка предполагает, что процессор будет следовать логам c: -)

Положительные целые числа следуют простой последовательности, отрицательные не гарантируют их представление.

Я написал подпрограмму для отображения цепочек битов из значений Фортрана, которая принимает пользовательский ввод в командной строке. Проверьте результат на ваш:

program bit_sizes
  use iso_fortran_env, only: int64
  implicit none
  integer(int64) :: n

  do while (.true.)
     write(*,*) 'enter value'
     read(*,*) n
     write(*,*) 'n', n
     write(*,*) 'popcnt(n)', popcnt(n)
     call print_bitstring(n)
     write(*,*) '-n', -n
     write(*,*) 'popcnt(-n)', popcnt(-n)
     call print_bitstring(-n)
  end do

contains

  subroutine assert(cond)
    logical, intent(in) :: cond
    if (.not. cond) error stop
  end subroutine assert

subroutine print_bitstring(i)
  integer(kind=int64), intent(in) :: i

  integer :: j, n
  character(len=:), allocatable :: bitstring
  n = bit_size(i)
  allocate(character(len=n) :: bitstring)

  do j = 1, n
     if (btest(i,j-1)) then
        bitstring(j:j) = '1'
     else
        bitstring(j:j) = '0'
     end if
  end do

  write(*,*) bitstring

end subroutine print_bitstring

end program bit_sizes

С gfortran на linux 64bit, у меня есть

$ ./bit_sizes 
 enter value
1
 n                    1
 popcnt(n)           1
 1000000000000000000000000000000000000000000000000000000000000000
 -n                   -1
 popcnt(-n)          64
 1111111111111111111111111111111111111111111111111111111111111111
 enter value
2
 n                    2
 popcnt(n)           1
 0100000000000000000000000000000000000000000000000000000000000000
 -n                   -2
 popcnt(-n)          63
 0111111111111111111111111111111111111111111111111111111111111111
 enter value
4294967296
 n           4294967296
 popcnt(n)           1
 0000000000000000000000000000000010000000000000000000000000000000
 -n          -4294967296
 popcnt(-n)          32
 0000000000000000000000000000000011111111111111111111111111111111
 enter value
2 голосов
/ 12 февраля 2020

Хороший друг из Electri c может помочь мне.

В моем понимании знак целого числа со знаком закодирован в один бит

Это как правило, не соответствует действительности.

Альтернативные представления:

https://en.wikipedia.org/wiki/Two%27s_complement

...