Fortran 整数的位大小
Bit sizes of Fortran integers
我有以下程序来举一个我不明白的最小例子
关于一般的位表示或 Fortran 中的位表示。
如果我使用 gfortran 7.5
或 ifort 18.0
进行编译,它会通过所有断言,但我不明白为什么。
函数popcnt returns I的二进制表示中设置的位数('1'位)
根据我的理解,有符号整数的符号以一位编码,因此如果我从 popcnt(n)
变为 popcnt(-n)
,它应该改变一位。
如果我可以将 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
电气工程的好朋友可以帮帮我
In my understanding the sign of a signed integer is encoded in one bit
这通常不是真的。
替代表示法是:
错误假设处理器将遵循该逻辑:-)
正整数遵循简单的级数,负整数在表示方面没有保证。
我编写了一个例程来显示来自 Fortran 值的位串,该值在命令行接受用户输入。查看您的结果:
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
在 linux 64 位上使用 gfortran,我有
$ ./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
我有以下程序来举一个我不明白的最小例子
关于一般的位表示或 Fortran 中的位表示。
如果我使用 gfortran 7.5
或 ifort 18.0
进行编译,它会通过所有断言,但我不明白为什么。
函数popcnt returns I的二进制表示中设置的位数('1'位)
根据我的理解,有符号整数的符号以一位编码,因此如果我从 popcnt(n)
变为 popcnt(-n)
,它应该改变一位。
如果我可以将 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
电气工程的好朋友可以帮帮我
In my understanding the sign of a signed integer is encoded in one bit
这通常不是真的。
替代表示法是:
错误假设处理器将遵循该逻辑:-)
正整数遵循简单的级数,负整数在表示方面没有保证。
我编写了一个例程来显示来自 Fortran 值的位串,该值在命令行接受用户输入。查看您的结果:
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
在 linux 64 位上使用 gfortran,我有
$ ./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