How do I do big integers in Fortran? - fortran

I need to generate some big integers. See example below.
Input Result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
Here is my Fortran code:
program cycle
use iso_fortran_env
implicit none
character(200) :: str
integer :: n
integer(kind=int64) :: x1, result, x2, x3
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
write(str,'(i64)') result
print *, n, adjustl(str)
end do
end program cycle
Here is the sample output:
40 165580141
80 37889062373143906
120 790376311979428689
160 9217463444206948445
200 3721511182311577122
As you can see, it gets the first two numbers right but the rest are beyond the reach of 64 bit integers. I've looked at other questions (1) but I'm really interested in a simple way, preferably built into the language itself. In Ruby and Go I have little trouble. Am I overlooking something obvious in Fortran? Is there a better option I can use in my code?

There is no built-in "big number" support, but we can first check whether there is a larger integer kind available (as mentioned by Francescalus above and also many previous pages (e.g. this page). On my computer with gfortran-6.1, the compiler seems to support 128-bit integer kind, so I could calculate the result up to n=160 or so.
program cycle
...
integer, parameter :: verylong = selected_int_kind(32)
integer(verylong) :: x1, result, x2, x3
print *, "int32 = ", int32 !! from iso_fortran_env
print *, "int64 = ", int64
print *
print *, "kind..(16) => ", selected_int_kind(16) !! 8
print *, "kind..(32) => ", selected_int_kind(32) !! 16
print *, "kind..(40) => ", selected_int_kind(40) !! -1 (not available)
print *, "kind..(64) => ", selected_int_kind(64) !! -1 (not available)
print *
print *, "sizeof(x1) = ", sizeof(x1), "(bytes)" !! GNU extension
print *, "storage_size(x1) = ", storage_size(x1), "(bits)" !! F2008
print *, "huge(x1) = ", huge(x1) !! largest integer
...
Results:
int32 = 4
int64 = 8
kind..(16) => 8
kind..(32) => 16
kind..(40) => -1
kind..(64) => -1
sizeof(x1) = 16 (bytes)
storage_size(x1) = 128 (bits)
huge(x1) = 170141183460469231731687303715884105727
n= 40 res= 165580141
n= 80 res= 37889062373143906
n= 120 res= 8670007398507948658051921
n= 160 res= 1983924214061919432247806074196061
n= 200 res= 37016692776042937155243383431825151522
n= 240 res= -159769225356713774587328406036589956191
...
While there is no built-in "BigInt" type, it is rather straightforward to use an external library (for example, fmlib linked from this page). Since various operators and assignment are overloaded, almost no modifications are necessary to your codes.
Procedures:
1) Download the file FMfiles.zip and extract FM.95, FMZM90.f95, and FMSAVE.f95
2) Make a library file as
gfortran -c -O2 FMSAVE.f95 FMZM90.f95 FM.f95
ar rv fmlib.a FM*.o
3) Modify your code as follows (the modified parts are marked with arrows).
program cycle
use FMZM !<----- a module for handling big numbers
implicit none
character(200) :: str
integer :: n
type(IM) :: x1, result, x2, x3 !<----- IM = BigInt, FM = BigFloat
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
str = IM_format( 'i200', result ) !<----- convert BigInt to string
print *, n, trim( adjustl(str) ) !<----- print huge integers
end do
end program cycle
4) Compile (assuming that "test.f90" is the above code):
gfortran test.f90 fmlib.a
./a.out
5) Results
n result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
240 103881042195729914708510518382775401680142036775841
280 23770696554372451866815101694984845480039225387896643963981
320 5439356428629292972296177350244602806380313370817060034433662955746
360 1244666864935793005828156005589143096022236302705537193166716344690085611761
400 284812298108489611757988937681460995615380088782304890986477195645969271404032323901
440 65172495098135102433647404982700073500075401759827878315356483347951218369680224170989749666
480 14913169640232740127827512057302148063648650711209401966150219926546779697987984279570098768737999681
We can verify the result by noting that result for n is actually equal to fibonacci(n+1), so for example we have fibonacci(481) for n = 480.

Related

How to increase N from 10 random points and up to 10^8 points in Monte Carlo [duplicate]

I want to double a number till 256, and when the program gets 256 make stop but the program that I created not giving me a double from 1 till 256
`````````````````````````````````````````````````````````````````
Fortran code
program exercise1
implicit none
real, external :: f
real :: h,a,b,prod,integration,summ,p
integer :: i,j,n
print*, 'Welcome, This program using Composite trapezoid method to calculate the integer'
print*, ' -------- '
prod=1
summ=0
print*,'Number of intervals ',' The integer value'
do i=1,258
n=(prod*i*i) ! Getting number of interval till 256
a=-1 ! The Lower limit of the integration
b=1 ! The Upper limit of the integration
h=(b-a)/n ! Calculate the delta X
p=(h/2.)*(f(a)+f(b)) ! Here as we have the whole equation is (h/2)*[f(a)+f(b)+2*sum(Xi) ! So we calculate the first part (h/2)*[f(a)+f(b) and then calculate the anoter part
summ=summ+h*f(a+i*h) !h/2 *2* sum[f(Xi)
integration = p+summ !Here the sum the both parts
if(n == 256) then !put a limit for the number of interval
Stop
end if
print*,n,' -', integration
enddo
end
real function f(x) !the function of the integer
f=sin(x+1)
end`
``````````````````````
the output
``````````````````
1 2.72789216
4 2.46665454
9 2.47777867
16 2.49350500
25 2.50419927
36 2.51126313
49 2.51606560
64 2.51944780
81 2.52190781
100 2.52374840
121 2.52515912
144 2.52626276
169 2.52714205
196 2.52785373
225 2.52843738
I think you want powers of: 2**i not squares: i**2. For example:
do i = 0,8
print*, 2**i
enddo
gives
1
2
4
8
16
32
64
128
256
I was originally voting to close as a typo, but your code maybe indeed does something different.
Your codes makes n to be a sequence if integer squares. 1^2, 2^2, 3^2 ... 16^2=256
But you wanted doubling the number, in that case just multiply n by 2.
n = 1
do i = 1, 10
do what you need
print *, n
n = n * 2
end do

How automatically double the number of intervals

I want to double a number till 256, and when the program gets 256 make stop but the program that I created not giving me a double from 1 till 256
`````````````````````````````````````````````````````````````````
Fortran code
program exercise1
implicit none
real, external :: f
real :: h,a,b,prod,integration,summ,p
integer :: i,j,n
print*, 'Welcome, This program using Composite trapezoid method to calculate the integer'
print*, ' -------- '
prod=1
summ=0
print*,'Number of intervals ',' The integer value'
do i=1,258
n=(prod*i*i) ! Getting number of interval till 256
a=-1 ! The Lower limit of the integration
b=1 ! The Upper limit of the integration
h=(b-a)/n ! Calculate the delta X
p=(h/2.)*(f(a)+f(b)) ! Here as we have the whole equation is (h/2)*[f(a)+f(b)+2*sum(Xi) ! So we calculate the first part (h/2)*[f(a)+f(b) and then calculate the anoter part
summ=summ+h*f(a+i*h) !h/2 *2* sum[f(Xi)
integration = p+summ !Here the sum the both parts
if(n == 256) then !put a limit for the number of interval
Stop
end if
print*,n,' -', integration
enddo
end
real function f(x) !the function of the integer
f=sin(x+1)
end`
``````````````````````
the output
``````````````````
1 2.72789216
4 2.46665454
9 2.47777867
16 2.49350500
25 2.50419927
36 2.51126313
49 2.51606560
64 2.51944780
81 2.52190781
100 2.52374840
121 2.52515912
144 2.52626276
169 2.52714205
196 2.52785373
225 2.52843738
I think you want powers of: 2**i not squares: i**2. For example:
do i = 0,8
print*, 2**i
enddo
gives
1
2
4
8
16
32
64
128
256
I was originally voting to close as a typo, but your code maybe indeed does something different.
Your codes makes n to be a sequence if integer squares. 1^2, 2^2, 3^2 ... 16^2=256
But you wanted doubling the number, in that case just multiply n by 2.
n = 1
do i = 1, 10
do what you need
print *, n
n = n * 2
end do

Need Help: Fortran Infinite Loop

I'm very new to using Fortran, and I can't seem to figure out why this subroutine is getting stuck in an infinite loop. Here's the code for said DO loop:
SUBROUTINE FILLARRAY(K, N)
REAL X, Y
INTEGER XPOS, YPOS
INTEGER K(N,N)
DO 10 I = 1, 100
15 CALL RANDOM_NUMBER(X)
CALL RANDOM_NUMBER(Y)
XPOS = 20 * X + 1.0
YPOS = 20 * Y + 1.0
PRINT *, XPOS
PRINT *, YPOS
IF(K(XPOS, YPOS).NE.1) THEN
K(XPOS,YPOS) = 1
END IF
IF (K(XPOS, YPOS).EQ.1) THEN
GOTO 15
END IF
10 CONTINUE
RETURN
END
I am basically trying to fill a 20 x 20 array randomly with the value 1.
I was also wondering if there is a way to forego using END IF that anyone knows about! Thank you!
The array will eventually all be set to 1 leading to an infinte loop with GOTO 15.
Try this code instead:
IF(K(XPOS, YPOS).NE.1) THEN
K(XPOS,YPOS) = 1
ELSE
GOTO 15
END IF
This method is horribly inefficient. I'd do it something like the below. Note i've filled with i rather than 1, partially to show the random order of filling, partially to act as a check I haven't screwed up, as each number should appear exactly once.
ian#eris:~/work/stack$ cat random_fill.f90
Program random_fill
Implicit None
Integer, Parameter :: n = 5
Integer, Dimension( 1:n, 1:n ) :: K
Call fillarray( k, n )
Write( *, '( 5( 5( i2, 1x ) / ) )' ) K
Contains
Subroutine fillarray( k, n )
Implicit None
Integer , Intent( In ) :: n
Integer, Dimension( 1:n, 1:n ), Intent( Out ) :: K
Integer, Dimension( : ), Allocatable :: index_list
Real :: rand
Integer :: val, x, y
Integer :: i
index_list = [ ( i, i = 0, n * n - 1 ) ]
Do i = 1, n * n
Call Random_number( rand )
val = 1 + Int( rand * Size( index_list ) )
x = 1 + index_list( val ) / n
y = 1 + Mod( index_list( val ), n )
K( x, y ) = i
index_list = [ index_list( :val - 1 ), index_list( val + 1: ) ]
End Do
End Subroutine fillarray
End Program random_fill
ian#eris:~/work/stack$ gfortran -O -Wall -Wextra -pedantic -fcheck=all -std=f2008 random_fill.f90
ian#eris:~/work/stack$ ./a.out
11 8 14 24 16
19 23 25 15 3
21 20 5 7 18
6 17 22 12 9
2 4 1 10 13
ian#eris:~/work/stack$ ./a.out
24 15 7 22 25
8 17 10 1 14
9 5 4 12 2
11 21 20 3 18
6 19 23 13 16
ian#eris:~/work/stack$ ./a.out
22 11 6 21 24
7 3 8 10 25
17 19 16 2 9
13 4 15 5 23
12 1 14 20 18
You are stuck in an infinite loop because the statement goto 15 is always executed.
If k(xpos, ypos) is 1 then the first if statement is false, but the second is true so the goto 15 is executed.
If instead k(xpos, ypos) is not 1 then the first if statement is true, and so k(xpos, ypos) is set to 1. The second if statement is only evaluated after this, and so is true, and so the goto 15 is executed.
As other answers have mentioned, the method you are using is horribly inefficient. However, if you still want to use it, here is the fixed code, with a number of modernisations:
subroutine fillarray(k, n)
implicit none
integer, intent(in) :: n
integer, intent(inout) :: k(n,n)
real(dp) :: x, y
integer :: xpos, ypos
integer :: i
i=1
do while (i<=100)
call random_number(x)
call random_number(y)
xpos = 20*x + 1.0_dp
ypos = 20*y + 1.0_dp
if (k(xpos, ypos)/=1) then
k(xpos, ypos) = 1
i = i+1
endif
enddo
end subroutine
Note that this assumes that the array k has already been initialised, otherwise checking the contents of the array will lead to undefined behaviour.
As to whether end if is optional or not. No, it is not optional. It is always required. All languages need to know where the end of a loop is. C uses }, Python uses un-indentation, Fortran uses endif.

Project Euler 29 in Fortran - Dealing with large integers [duplicate]

I need to generate some big integers. See example below.
Input Result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
Here is my Fortran code:
program cycle
use iso_fortran_env
implicit none
character(200) :: str
integer :: n
integer(kind=int64) :: x1, result, x2, x3
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
write(str,'(i64)') result
print *, n, adjustl(str)
end do
end program cycle
Here is the sample output:
40 165580141
80 37889062373143906
120 790376311979428689
160 9217463444206948445
200 3721511182311577122
As you can see, it gets the first two numbers right but the rest are beyond the reach of 64 bit integers. I've looked at other questions (1) but I'm really interested in a simple way, preferably built into the language itself. In Ruby and Go I have little trouble. Am I overlooking something obvious in Fortran? Is there a better option I can use in my code?
There is no built-in "big number" support, but we can first check whether there is a larger integer kind available (as mentioned by Francescalus above and also many previous pages (e.g. this page). On my computer with gfortran-6.1, the compiler seems to support 128-bit integer kind, so I could calculate the result up to n=160 or so.
program cycle
...
integer, parameter :: verylong = selected_int_kind(32)
integer(verylong) :: x1, result, x2, x3
print *, "int32 = ", int32 !! from iso_fortran_env
print *, "int64 = ", int64
print *
print *, "kind..(16) => ", selected_int_kind(16) !! 8
print *, "kind..(32) => ", selected_int_kind(32) !! 16
print *, "kind..(40) => ", selected_int_kind(40) !! -1 (not available)
print *, "kind..(64) => ", selected_int_kind(64) !! -1 (not available)
print *
print *, "sizeof(x1) = ", sizeof(x1), "(bytes)" !! GNU extension
print *, "storage_size(x1) = ", storage_size(x1), "(bits)" !! F2008
print *, "huge(x1) = ", huge(x1) !! largest integer
...
Results:
int32 = 4
int64 = 8
kind..(16) => 8
kind..(32) => 16
kind..(40) => -1
kind..(64) => -1
sizeof(x1) = 16 (bytes)
storage_size(x1) = 128 (bits)
huge(x1) = 170141183460469231731687303715884105727
n= 40 res= 165580141
n= 80 res= 37889062373143906
n= 120 res= 8670007398507948658051921
n= 160 res= 1983924214061919432247806074196061
n= 200 res= 37016692776042937155243383431825151522
n= 240 res= -159769225356713774587328406036589956191
...
While there is no built-in "BigInt" type, it is rather straightforward to use an external library (for example, fmlib linked from this page). Since various operators and assignment are overloaded, almost no modifications are necessary to your codes.
Procedures:
1) Download the file FMfiles.zip and extract FM.95, FMZM90.f95, and FMSAVE.f95
2) Make a library file as
gfortran -c -O2 FMSAVE.f95 FMZM90.f95 FM.f95
ar rv fmlib.a FM*.o
3) Modify your code as follows (the modified parts are marked with arrows).
program cycle
use FMZM !<----- a module for handling big numbers
implicit none
character(200) :: str
integer :: n
type(IM) :: x1, result, x2, x3 !<----- IM = BigInt, FM = BigFloat
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
str = IM_format( 'i200', result ) !<----- convert BigInt to string
print *, n, trim( adjustl(str) ) !<----- print huge integers
end do
end program cycle
4) Compile (assuming that "test.f90" is the above code):
gfortran test.f90 fmlib.a
./a.out
5) Results
n result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
240 103881042195729914708510518382775401680142036775841
280 23770696554372451866815101694984845480039225387896643963981
320 5439356428629292972296177350244602806380313370817060034433662955746
360 1244666864935793005828156005589143096022236302705537193166716344690085611761
400 284812298108489611757988937681460995615380088782304890986477195645969271404032323901
440 65172495098135102433647404982700073500075401759827878315356483347951218369680224170989749666
480 14913169640232740127827512057302148063648650711209401966150219926546779697987984279570098768737999681
We can verify the result by noting that result for n is actually equal to fibonacci(n+1), so for example we have fibonacci(481) for n = 480.

How to bignum in Fortran [duplicate]

I need to generate some big integers. See example below.
Input Result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
Here is my Fortran code:
program cycle
use iso_fortran_env
implicit none
character(200) :: str
integer :: n
integer(kind=int64) :: x1, result, x2, x3
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
write(str,'(i64)') result
print *, n, adjustl(str)
end do
end program cycle
Here is the sample output:
40 165580141
80 37889062373143906
120 790376311979428689
160 9217463444206948445
200 3721511182311577122
As you can see, it gets the first two numbers right but the rest are beyond the reach of 64 bit integers. I've looked at other questions (1) but I'm really interested in a simple way, preferably built into the language itself. In Ruby and Go I have little trouble. Am I overlooking something obvious in Fortran? Is there a better option I can use in my code?
There is no built-in "big number" support, but we can first check whether there is a larger integer kind available (as mentioned by Francescalus above and also many previous pages (e.g. this page). On my computer with gfortran-6.1, the compiler seems to support 128-bit integer kind, so I could calculate the result up to n=160 or so.
program cycle
...
integer, parameter :: verylong = selected_int_kind(32)
integer(verylong) :: x1, result, x2, x3
print *, "int32 = ", int32 !! from iso_fortran_env
print *, "int64 = ", int64
print *
print *, "kind..(16) => ", selected_int_kind(16) !! 8
print *, "kind..(32) => ", selected_int_kind(32) !! 16
print *, "kind..(40) => ", selected_int_kind(40) !! -1 (not available)
print *, "kind..(64) => ", selected_int_kind(64) !! -1 (not available)
print *
print *, "sizeof(x1) = ", sizeof(x1), "(bytes)" !! GNU extension
print *, "storage_size(x1) = ", storage_size(x1), "(bits)" !! F2008
print *, "huge(x1) = ", huge(x1) !! largest integer
...
Results:
int32 = 4
int64 = 8
kind..(16) => 8
kind..(32) => 16
kind..(40) => -1
kind..(64) => -1
sizeof(x1) = 16 (bytes)
storage_size(x1) = 128 (bits)
huge(x1) = 170141183460469231731687303715884105727
n= 40 res= 165580141
n= 80 res= 37889062373143906
n= 120 res= 8670007398507948658051921
n= 160 res= 1983924214061919432247806074196061
n= 200 res= 37016692776042937155243383431825151522
n= 240 res= -159769225356713774587328406036589956191
...
While there is no built-in "BigInt" type, it is rather straightforward to use an external library (for example, fmlib linked from this page). Since various operators and assignment are overloaded, almost no modifications are necessary to your codes.
Procedures:
1) Download the file FMfiles.zip and extract FM.95, FMZM90.f95, and FMSAVE.f95
2) Make a library file as
gfortran -c -O2 FMSAVE.f95 FMZM90.f95 FM.f95
ar rv fmlib.a FM*.o
3) Modify your code as follows (the modified parts are marked with arrows).
program cycle
use FMZM !<----- a module for handling big numbers
implicit none
character(200) :: str
integer :: n
type(IM) :: x1, result, x2, x3 !<----- IM = BigInt, FM = BigFloat
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
str = IM_format( 'i200', result ) !<----- convert BigInt to string
print *, n, trim( adjustl(str) ) !<----- print huge integers
end do
end program cycle
4) Compile (assuming that "test.f90" is the above code):
gfortran test.f90 fmlib.a
./a.out
5) Results
n result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
240 103881042195729914708510518382775401680142036775841
280 23770696554372451866815101694984845480039225387896643963981
320 5439356428629292972296177350244602806380313370817060034433662955746
360 1244666864935793005828156005589143096022236302705537193166716344690085611761
400 284812298108489611757988937681460995615380088782304890986477195645969271404032323901
440 65172495098135102433647404982700073500075401759827878315356483347951218369680224170989749666
480 14913169640232740127827512057302148063648650711209401966150219926546779697987984279570098768737999681
We can verify the result by noting that result for n is actually equal to fibonacci(n+1), so for example we have fibonacci(481) for n = 480.