Getting the prime numbers till 10000 in fortran? - fortran

Im trying to print prime numbers till 10000. (display the first five for testing)
This is my program
program primes
implicit none
integer :: array(1229)
integer :: i, ind
logical :: is_prime
ind = 1
do i = 2, 10000, 1
if (is_prime(i) .eqv. .true.) then
array(ind) = i
ind = ind + 1
end if
end do
print *, array(1)
print *, array(2)
print *, array(3)
print *, array(4)
print *, array(5)
end program primes
function is_prime(n) result(ispr)
implicit none
integer :: c, i
integer, intent(in) :: n
logical :: ispr
c = 0
do i = 2, n
if (mod(i,2) == 0) then
c = c + 1
end if
end do
ispr = (c == 0)
end function is_prime
I don't know why but this is the output
9175178
6417360
5374044
6750309
7536745
Why does this happen and how to correct?

is_prime should be(n is the only divider of n besides 1 <=> c == 1)
function is_prime(n) result(ispr)
implicit none
integer :: c, i
integer, intent(in) :: n
logical :: ispr
c = 0
do i = 2, n
if (mod(n,i) == 0) then
c = c + 1
end if
end do
ispr = (c == 1)
end function is_prime
Could be optimezed by leaving the loop when c == 1 and i < n(after adding 1 to c)...
See on online fortran compiler
version with exit loop

While I am not familiar with modern Fortran, it looks to me as if function is_prime(n) result(ispr) is not working.
In the do loop in that function, you want a loop that tests thus:
is n divisible by 2?
is n divisible by 3?
is n divisible by 4?
is n divisible by 5?
and so on.
But, what it is actually doing is asking these:
is 2 divisible by 2?
is 3 divisible by 2?
is 4 divisible by 2?
is 5 divisible by 2?
and so on.
As a result, your counter will always have a non-zero value, and your function will always return false.
But, that's not the only problem. From your results, it looks like your Fortran implementation does not automatically initialize variables. Suppose I have statements like the following:
integer :: b
print *,b
What will be the result?
Remember, the names of variables represent locations in the computer's memory. If a variable is not initialized, it's value will be what was in the memory location before your program started to run. This value will not be related to your program.
I have 2 suggestions to fix the 2nd problem:
Prior to do i = 2, 10000, 1, have another loop that sets each value in array.
Set a values of each array (i) inside your do i = 2, 10000, 1 loop. One way to do this is to set one value when (is_prime(i) .eqv. .true.) is true and a different value when it is false.

Related

Fortran. do while with function checking the prime number [duplicate]

This question already has answers here:
Does Fortran preserve the value of internal variables through function and subroutine calls?
(3 answers)
Closed 2 years ago.
I'm recently studying Fortran, and trying to make a program to check the prime number. The function works fine without any loop. It can give 1 when the given number is a prime number and 0 otherwise. However, it doesn't work properly when it is used in do while loop. In the range of 2 ~ 10, it is supposed to give 1 (for 2), 1(for 2), 0(for 4), 1(for 5), 0(for 6), etc. But, it keeps showing only 0. I'm pretty new to programming, so I'm not sure what I'm missing. I know there are many answers related to prime numbers, but I don't see any issue like this.
** Function checking prime numbers **
module prime_function
contains
integer function isPrime(inp_num)
implicit none
integer :: inp_num
integer :: i = 1
integer :: temp1 = 0
do while (i < inp_num)
i = i + 1
if(mod(inp_num, i) == 0) then
exit
end if
end do
if(inp_num == i) then
temp1 = 1
else
temp1 = 0
end if
isPrime = temp1
end function
end module
program fortran_q
use prime_function
implicit none
integer :: ii, a
a = isPrime(10)
print *, "10 is prime number, so the return : ", a
a = isPrime(11)
print *, "11 is prime number, so the return : ", a
ii = 1
do while (ii < 10)
ii = ii + 1
print *, isPrime(ii)
end do
end program
** Results **
10 is prime number, so the return : 0
11 is prime number, so the return : 1
0
0
0
0
0
0
0
0
0
You have a classic issue for people new to Fortran. The initialization of i and temp0 implies the SAVE attribute. When you call isPrime for the first time the values are set to 1 and 0. On the next invocation, the values of i and temp0 are set to whatever their previous values were when isPrime was last executed. The belong program fixes the issue.
module prime_function
implicit none
private
public isprime
contains
function isPrime(inp_num) result(res)
integer res
integer, intent(in) :: inp_num
integer i, temp1
i = 1
temp1 = 0
do while (i < inp_num)
i = i + 1
if (mod(inp_num, i) == 0) exit
end do
res = 0
if (inp_num == i) res = 1
end function
end module
program fortran_q
use prime_function
implicit none
integer :: ii, a
a = isPrime(10)
print *, "10 is prime number, so the return : ", a
a = isPrime(11)
print *, "11 is prime number, so the return : ", a
ii = 1
do while (ii < 10)
ii = ii + 1
print *, isPrime(ii)
end do
end program

How to obtain the smallest figure out of five figures using OO Fortran

In what way can I get the smallest figure in a given five digit figure. E.g 23764. How do I get 2 being the smallest.
Taking the figure as a digit such as 456879, in order to obtain the smallest from the digit which is 4, I implemented the following
program findsmallestFigure
implicit none
integer:: figure
integer:: c,smallest,largest
smallest = 9
largest = 0
figure = 23456
do while(figure .GT. 0 )
c = MOD(figure,10)
largest = max(c,largest)
smallest = min(c,smallest)
figure = figure/10
end do
print *,'The smallest digit is',smallest
end
How do I achieve the same result using Object Oriented approach in Fortran ?
Create a module with a user-defined type that contains all the results, and the subroutines to fill in the values
module numstat
! Holds the statistics of a figure
type stat
integer :: smallest, largest, count
end type
! Constructor from a figure. Invoke by 'stat(1234)`
interface stat
module procedure :: calc_stat
end interface
contains
! Fill statistics type from a figure
function calc_stat(fig) result(s)
integer, intent(in) :: fig
type(stat) :: s
integer :: digit, f
! make a copy of the figure because intent(in) arguments
! are immutable (cannot change).
f = fig
s%smallest = 9
s%largest = 0
s%count = 0
do while(f > 0 )
s%count = s%count + 1
digit = mod(f, 10)
s%largest = max(s%largest, digit)
s%smallest = min(s%smallest, digit)
f = f/10
end do
end function
end module
Then use the module in the main program
program SONumstat
use numstat
implicit none
type(stat) :: s
integer :: figure
figure = 23456
s = stat(figure)
print *,'The number of digits is ', s%count
print *,'The smallest digit is ',s%smallest
print *,'The largest digit is ',s%largest
end program SONumstat

Code to Sum up the first 1234 multiples of 3 and 5 does not print anything

I'm trying to write some Fortran 90 code to sum up the first 1234 multiples of 3 and 5 (including multiples of both). Here is my code so far:
program sum
implicit none
integer :: x
integer :: y = 5
integer :: z = 3
integer :: n
if (mod(x,y) == 0 .or. mod(x,z) ==0) then
print *, x
n = x
n = x + x
end if
end program sum
However, this code does not print anything to the terminal.
Your code tests the value of x in the if condition:
if (mod(x,y) == 0 .or. mod(x,z) ==0
but the value of x is not set at all. Therefore the result of the program is completely undefined. You need to create some kind of loop. Better two loops.
The most naive approach is to loop from 1 and test all numbers with the above if condition and stop when you have found the desired number of multiples.

FORTRAN logic notproblem

If I just use my function once, it works properly. If I make it do a loop like down below, the four lines of commented code, my code malfunctions. I can't really figure out why it will always return T or F for every other number after the initial value.
Asterisks are in the parenthesis of WRITE and READ but it doesn't show up here for some reason.
PROGRAM PRIME
INTEGER :: N = 0, i = 1,x = 0
LOGICAL :: IP
WRITE (*,*) "Enter a number:"
READ (*,*) N
!DO WHILE ( N < 1000)
IP = IsPrime(N)
WRITE (*,*) IP, N
!N = N + 1
!END DO
read(*,*) x
CONTAINS
FUNCTION IsPrime(N)
LOGICAL :: IsPrime
INTEGER, INTENT(IN) :: N
IsPrime = .TRUE.
IF (N == 2) THEN
WRITE (*,*) N
ELSE
DO WHILE (i <= (N/2))
i = i + 2
IF (mod(N,i) == 0) THEN
IsPrime = .FALSE.
END IF
END DO
END IF
RETURN
END FUNCTION IsPrime
END PROGRAM PRIME
You're forgetting to reset i to 1 during each call to IsPrime.
The first time IsPrime is called, i=1 from the top of program main. However, i is incremented during the first IsPrime call to something other than 1 so the second call starts with i/=0.
Note that because IsPrime is contained within program main, IsPrime inherits i from program main.
I'm also bound to remind you to use implicit none everywhere to avoid other errors, although it's not a problem in this case.

Count the numbers of equal rows in a file

Suppose you have a file.dat of the form:
1
1
1
2
2
3
3
3
3
...
I want to count how many equal numbers there are and save them iteratively in a string. For instance:
m = 3 (times 1),
m = 2 (times 2),
m = 4 (times 3).
I put here my code:
program sele
implicit none
integer::j,k,s,n,l,r,m
real*8,allocatable::ID(:)
real*8:: j_r8,i_r8
open(10,file='data.dat')
n=0
DO
READ(10,*,END=100)
n=n+1
END DO
100 continue
rewind(10)
allocate(ID(n))
s=0
do s=1, n
read(10,*) ID(s)
end do
do r=1,n-1
if (ID(r)-ID(r+1) .EQ. 0) then
m = m + 1
print*, m
end if
end do
end program
The last do is the condition I'd like to expand, with something like:
if (condition is true) then
save an index of the number of equal digits
use this to do some operations:
do i = 1, number of equal digits
if (condition is not true) then
restart with the other digits.
If the values you want to read are integer values in a given limited range (for instance from 1 to 100), then the simplest way is the following :
program sele
implicit none
integer, parameter :: vmin=1
integer, parameter :: vmax=100
integer :: list(vmin:vmax)
integer :: value,i
open(10,file='data.dat')
list=0
do
read(10,*,end=10) value
if(value < vmin .OR. value > vmax) then
write(*,*) 'invalid value ',value
stop
endif
list(value)=list(value)+1
enddo
10 continue
do i=vmin,vmax
if(list(i) > 0) then
write(*,*) list(i),' times ',i
endif
enddo
end program
Which gives on your example :
3 times 1
2 times 2
4 times 3
It is possible to improve easily that program to manage variable vmin and vmax (the array list must then be declared allocatable and allocated at the right size).
If the range is too large, then a simple array is not accurate anymore and the right algorithm becomes more complicated : it must avoid to store unused values.