I have a problem with my Fortran program that does nothing more than calculating a prime factorization (or should do). That's the error:
C:\MinGW\Fortran>gfortran aufg3.f90
aufg3.f90:15.15:
if (prim(i) != 0 .and. modulo(n, prim(i)) == 0) then
1
Error: Missing ')' in statement at or before (1)
aufg3.f90:19.7:
end if
1
Error: Expecting END DO statement at (1)
aufg3.f90:34.13:
if (prim(i) != 0) then
1
Error: Missing ')' in statement at or before (1)
aufg3.f90:38.5:
end if
1
Error: Expecting END DO statement at (1)
I tried everything, but totally have no idea what could be wrong. Thanks for your help. Here is the code:
program aufg3
implicit none
integer :: n, i
integer, allocatable, dimension(:) :: prim
do
print *, 'Bitte natürliche Zahl eingeben, "0" für Abbruch: '
read *, n
if (n == 0) exit
allocate(prim(2:n))
call era(prim, n)
print *, n, ' = 1'
do
if (n == 1) exit
do i = 2, n
if (prim(i) != 0 .and. modulo(n, prim(i)) == 0) then
print *, ' * ', prim(i)
n = n / prim(i)
exit
end if
end do
end do
deallocate(prim)
end do
end program
subroutine era(prim, m)
integer, intent(in) :: m
integer, dimension(2:m) :: prim
integer :: i, j
do i = 2, m
prim(i) = i
end do
do i = 2, integer(sqrt(real(m)))
if (prim(i) != 0) then
do j = i*i, m, i
prim(j) = 0
end do
end if
end do
end subroutine
Well, this is Fortran and ! denotes a comment. So the compiler actually sees
if (prim(i)
which is no valid statement. The error message you see reflects that.
"Not equal" in Fortran is /= or .ne.:
if (prim(i) /= 0 .and. modulo(n, prim(i)) == 0) then
and, later on:
if (prim(i) /= 0) then
You're using the wrong notation for 'not equal to'. Fortran syntax is /= or .NE..
So you should be using:
if (prim(i) /= 0 .and. modulo(n, prim(i)) == 0) then
and
if (prim(i) /= 0) then
Furthermore, your syntax of integer(sqrt(real(m))) is incorrect, perhaps you mean NINT(sqrt(real(m)))?
The token for "not equals" in fortran is /= . ! starts a comment, hence the compiler reading line 15 as
if (prim(i)
and so is confused because there is no bracket to close the logical expression in the if statement. So simply replace != with /= and it should get rid of this problem.
Related
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.
So apparently, depending in wether i tell the program to print the variable i, or not, I get different results that should not have anything to do with wether i print it our or not.
PROGRAM hello
IMPLICIT NONE
integer :: n,i, mini
logical :: leave = .false.
read*, n
print*, is_prime(n)
!!---------------------------------------------------------------------
do i=n, n/2, -1
print*, "I= ", i !!if you comment out this line, the result will be different than if you were to keep it, try it out yourselves
if(is_prime(i)) then
mini = i
end if
end do
print*, "the lowest prime number between your number and its half is: ", mini
!!----------------------------------------------------------
CONTAINS
logical function is_prime(n)
integer::n,i
do i=2,n
if(mod(n,i) == 0 .and. (i/=1 .and. i/=n) ) then
is_prime = .false.
elseif(mod(n,i) /=0 .and. i == n-1 .and. is_prime .neqv. .false.) then
is_prime = .true.
end if
end do
return
end function
END PROGRAM
So if you were to comment out the line I pointed out, the result of "mini" will be different than if you were to keep it, as I said.
I'm fairly new at fortran so I don't know wether I'm doing something wrong, or if this has something to do with the compiler, but it seems really weird to me that putting a print*, line would in any way change the value of the variabe, and that's what seems to happen.
For example if you try it yourselve, the output of mini when the print line is in, is for exaple,, typing in 48, is 29, which is right, it's the minimum prime number between 48 and ts half, but when you tipe in 48 and the famous print line is commented out, the output will be -2, instead of 29.
Any of you know why this happenes?
#francescalus is right, the logic of is_prime is wrong.
You can tell by checking the first result (the print *, is_prime(n)) of the program.
Below, a version with a correct is_prime. I first assign .true. to the result and invalidate it to .false. when the test is true.
PROGRAM hello
IMPLICIT NONE
integer :: n,i, mini
read*, n
print*, is_prime(n)
!!---------------------------------------------------------------------
do i=n, n/2, -1
print*, "I= ", i
if(is_prime(i)) then
mini = i
end if
end do
print*, "the lowest prime number between your number and its half is: ", mini
!!----------------------------------------------------------
CONTAINS
logical function is_prime(n)
integer, intent(in) :: n
integer :: i
is_prime = .true.
do i=2,n
if(mod(n,i) == 0 .and. (i/=1 .and. i/=n) ) then
is_prime = .false.
end if
end do
end function is_prime
END PROGRAM
EDIT: I should add that the issue with the influence of the print statement comes up from time to time. When it arises, it points to a flaw in the logic of the code that then becomes sensitive to situations of ill-defined results.
I have a problem with my Fortran program that does nothing more than calculating a prime factorization (or should do). That's the error:
C:\MinGW\Fortran>gfortran aufg3.f90
aufg3.f90:15.15:
if (prim(i) != 0 .and. modulo(n, prim(i)) == 0) then
1
Error: Missing ')' in statement at or before (1)
aufg3.f90:19.7:
end if
1
Error: Expecting END DO statement at (1)
aufg3.f90:34.13:
if (prim(i) != 0) then
1
Error: Missing ')' in statement at or before (1)
aufg3.f90:38.5:
end if
1
Error: Expecting END DO statement at (1)
I tried everything, but totally have no idea what could be wrong. Thanks for your help. Here is the code:
program aufg3
implicit none
integer :: n, i
integer, allocatable, dimension(:) :: prim
do
print *, 'Bitte natürliche Zahl eingeben, "0" für Abbruch: '
read *, n
if (n == 0) exit
allocate(prim(2:n))
call era(prim, n)
print *, n, ' = 1'
do
if (n == 1) exit
do i = 2, n
if (prim(i) != 0 .and. modulo(n, prim(i)) == 0) then
print *, ' * ', prim(i)
n = n / prim(i)
exit
end if
end do
end do
deallocate(prim)
end do
end program
subroutine era(prim, m)
integer, intent(in) :: m
integer, dimension(2:m) :: prim
integer :: i, j
do i = 2, m
prim(i) = i
end do
do i = 2, integer(sqrt(real(m)))
if (prim(i) != 0) then
do j = i*i, m, i
prim(j) = 0
end do
end if
end do
end subroutine
Well, this is Fortran and ! denotes a comment. So the compiler actually sees
if (prim(i)
which is no valid statement. The error message you see reflects that.
"Not equal" in Fortran is /= or .ne.:
if (prim(i) /= 0 .and. modulo(n, prim(i)) == 0) then
and, later on:
if (prim(i) /= 0) then
You're using the wrong notation for 'not equal to'. Fortran syntax is /= or .NE..
So you should be using:
if (prim(i) /= 0 .and. modulo(n, prim(i)) == 0) then
and
if (prim(i) /= 0) then
Furthermore, your syntax of integer(sqrt(real(m))) is incorrect, perhaps you mean NINT(sqrt(real(m)))?
The token for "not equals" in fortran is /= . ! starts a comment, hence the compiler reading line 15 as
if (prim(i)
and so is confused because there is no bracket to close the logical expression in the if statement. So simply replace != with /= and it should get rid of this problem.
I am writing a program in Fortran 95 (to be compiled with with gfortran) containing a subroutine that performs a certain computation. As suggested in "Fortran 95/2003 for Scientists & Engineers" by S. J. Chapman, I am trying to stop the subroutine when an error is encountered and "throw"[1] an error flag that is "catch"ed[1] by the calling program, that will take all the necessary actions. Ideally, I am going for something like:
! Pseudo-code
PROGRAM my_prog
integer :: error_flag
CALL my_subr (<input_args>, <output_args>, error_flag)
! Also error_flag is an output: 0 -> everything OK, 1 -> error
IF (error_flag /= 0) THEN
WRITE (*,*) 'Error during execution of "my_subr"'
ELSE
... do something ...
END IF
END PROGRAM my_prog
How can I stop the subroutine and gracefully handle the errors?
Here is an example: the subroutine "division" takes an integer input value and iteratively divides it by a value that is the input value decremented by the number of steps-1. When such value reaches zero, a flag should be raised and the subroutine should be exited without performing the division by zero.
SUBROUTINE division (inval, outval, error_flag)
IMPLICIT NONE
INTEGER, INTENT(IN) :: inval
REAL, INTENT(OUT) :: outval
INTEGER, INTENT(OUT) :: error_flag ! 0 -> OK, 1 -> error
INTEGER :: i
REAL :: x
error_flag = 0
x = REAL(inval)
DO i = 0, 10
IF (inval-i == 0) error_flag = 1
! How can I gracefully exit now?
x = x / REAL(inval-i)
END DO
END SUBROUTINE division
PROGRAM my_prog
IMPLICIT NONE
REAL :: outval
INTEGER :: error_flag
CALL division (8, outval, error_flag)
IF (error_flag == 1) THEN
WRITE (*,*) 'Division by zero'
ELSE
WRITE (*,*) 'Output value:', outval
END IF
END PROGRAM my_prog
Notes:
[1] I am borrowing (in a probably inappropriate way) C++'s jargon.
Seeing your example it seems that you are just missing the return statement:
error_flag = 0
x = REAL(inval)
DO i = 0, 10
IF (inval-i == 0) then
error_flag = 1
return
END IF
x = x / REAL(inval-i)
END DO
One possibility would be to change
DO i = 0, 10
IF (inval-i == 0) error_flag = 1
! How can I gracefully exit now?
x = x / REAL(inval-i)
END DO
to
DO i = 0, 10
IF (inval-i == 0) THEN
error_flag = 1
EXIT
END IF
! Now you have gracefully exited
x = x / REAL(inval-i)
END DO
! Code to tidy up if the error flag was set
Here the EXIT statement exits the loop -- Vladimir's answer shows you how to use RETURN to exit the subroutine more immediately. Whichever approach you choose don't forget to assign to outval before leaving the subroutine.
I'm a Fortran 77 learner, I'm new so don'n know much about Fortran.
Our professor gave us a homework. We suppose to write a program that calculates cos(x**2).
It has a Taylor expansion, so I tried to write some things but It gave me this error:
term = term*((-1)**i)*x**2*i)/fac(2*i)
1
Error: Unclassifiable statement at (1)
The hole program is:
PROGRAM COSX_SQUARE
IMPLICIT NONE
INTEGER x, n, i
REAL partial_sum, term
20 PRINT*, 'INPUT THE DEGREE'
READ*, x
x = x*180/3.1415
PRINT*, 'INPUT THE CORRECTION VALUE '
PRINT*, 'AS A NATURAL NUMBER'
READ*, n
i= -1
term = 1
partial_sum = term
10 i=i+1
term = term*((-1)**i)*x**2*i)/fac(2*i)
partial_sum = partial_sum + term
IF (i .LT. n) THEN
GO TO 10
ELSE
PRINT*, 'COS', x, 'SQUARE IS = ', partial_sum
END IF
GO TO 20
END
Where am I mistaking? And will this program work well? Thanks in advance.
You are missing one bracket in your expression!
It should probably read:
term = term*(((-1)**i)*x**2*i)/fac(2*i)