Solving quadratic equation but getting weird errors - fortran

I'm attempting my first program in Fortran, trying to solve a quadratic equation. I have double and triple checked my code and don't see anything wrong. I keep getting "Invalid character in name at (1)" and "Unclassifiable statement at (1)" at various locations. What is wrong with the code?
! This program solves quadratic equations
! of the form ax^2 + bx + c = 0.
! Record:
! Name: Date: Notes:
! Damon Robles 4/3/10 Original Code
PROGRAM quad_solv
IMPLICIT NONE
! Variables
REAL :: a, b, c
REAL :: discrim, root1, root2,
COMPLEX :: comp1, comp2
CHARACTER(len=1) :: correct
! Prompt user for coefficients.
WRITE(*,*) "This program solves quadratic equations "
WRITE(*,*) "of the form ax^2 + bx + c = 0. "
WRITE(*,*) "Please enter the coefficients a, b, and "
WRITE(*,*) "c, separated by commas:"
READ(*,*) a, b, c
WRITE(*,*) "Is this correct: a = ", a, " b = ", b
WRITE(*,*) " c = ", c, " [Y/N]? "
READ(*,*) correct
IF correct = N STOP
IF correct = Y THEN
! Definition
discrim = b**2 - 4*a*c
! Calculations
IF discrim > 0 THEN
root1 = (-b + sqrt(discrim))/(2*a)
root2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "This equation has two real roots. "
WRITE(*,*) "x1 = ", root1
WRITE(*,*) "x2 = ", root2
IF discrim = 0 THEN
root1 = -b/(2*a)
WRITE(*,*) "This equation has a double root. "
WRITE(*,*) "x1 = ", root1
IF discrim < 0 THEN
comp1 = (-b + sqrt(discrim))/(2*a)
comp2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "x1 = ", comp1
WRITE(*,*) "x2 = ", comp2
PROGRAM END quad_solv

Re the additional question of how to loop back to redo input -- an example program demonstrating loop features of Fortran >= 90. The loop is apparently infinite -- exit controlled by the IF statement exits the loop and makes the loop finite. Also shown is the cycle control, which is used if invalid input is encountered, which would otherwise crash the program. (For example, type "A" as input to the first read, instead of a number.) In this case, the iostat variable acquires a non-zero value, the IF statement activates the cycle, and the rest of the DO loop is skipped, so that the loop cycles anew.
program test_readdata
real :: a, b, c
integer :: ReturnCode
character (len=1) :: correct
ReadData: do
write (*, '( "This program solves quadratic equations of the form ax^2 + bx + c = 0. " )' )
write (*, '( "Please enter the coefficients a, b, and c, separated by commas: " )', advance='no' )
read (*,*, iostat=ReturnCode) a, b, c
if ( ReturnCode /= 0 ) cycle ReadData
write (*,*) "Is this correct: a = ", a, " b = ", b, " c = ", c
write (*, '( "Enter Y or N: " )', advance='no' )
read (*,*, iostat=ReturnCode) correct
if ( ReturnCode /= 0 ) cycle ReadData
if ( correct == 'Y' .or. correct == 'y' ) exit ReadData
end do ReadData
stop
end program test_readdata
My book recommendation: Fortran 95/2003 explained by Metcalf, Reid and Cohen.

The first thing I noticed with your code is the syntax error at the end of your program.
END
should have preceded the word program
Doesn't your editor highlight your syntax errors?
You can get the student version of ELF 90 pretty inexpensively and it's a good place to start. I would then upgrade to Lahey ELF 95 with the Visual Studio and algorithm flow chart generator which color codes the pathways of the passing of the values.

So many errors... It seems you don't know Fortran basics...
With minimal corrections
! This program solves quadratic equations
! of the form ax^2 + bx + c = 0.
! Record:
! Name: Date: Notes:
! Damon Robles 4/3/10 Original Code
PROGRAM quad_solv
IMPLICIT NONE
! Variables
REAL :: a, b, c
REAL :: discrim, root1, root2
COMPLEX :: comp1, comp2
CHARACTER(len=1) :: correct
! Prompt user for coefficients.
WRITE(*,*) "This program solves quadratic equations "
WRITE(*,*) "of the form ax^2 + bx + c = 0. "
WRITE(*,*) "Please enter the coefficients a, b, and "
WRITE(*,*) "c, separated by commas:"
READ(*,*) a, b, c
WRITE(*,*) "Is this correct: a = ", a, " b = ", b
WRITE(*,*) " c = ", c, " [Y/N]? "
READ(*,*) correct
IF (correct == 'N') STOP
IF (correct == 'Y') THEN
! Definition
discrim = b**2 - 4*a*c
! Calculations
IF (discrim > 0) THEN
root1 = (-b + sqrt(discrim))/(2*a)
root2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "This equation has two real roots. "
WRITE(*,*) "x1 = ", root1
WRITE(*,*) "x2 = ", root2
ELSEIF (discrim == 0) THEN
root1 = -b/(2*a)
WRITE(*,*) "This equation has a double root. "
WRITE(*,*) "x1 = ", root1
ELSE
comp1 = (-b + sqrt(discrim))/(2*a)
comp2 = (-b - sqrt(discrim))/(2*a)
WRITE(*,*) "x1 = ", comp1
WRITE(*,*) "x2 = ", comp2
END IF
END IF
END PROGRAM quad_solv
P.S. I didn't check the correctness.
P.P.S. Always indent your code to make it readable and don't use STOP statement. Each program (or subroutine) should have one entry and one exit. The only right place for STOP is exactly before END PROGRAM statement where it is redundant. So don't use STOP at all.

Some changes: correct IF syntax; constants to be real numbers rather than integers, when appropriate:
IF (CORRECT == "N" ) stop
if ( discrim > 0.0 ) then
Apply at additional locations, and you should be very close. Good luck.
It can be a poor algorithm to test a floating point number for having an exact value. What if rounding error makes disrim have the value 1.0E-30, when perfect arithmetic would give the value zero and indicate a double root?

Related

write(*,'(A,g0.1,A,F10.2,A,F10.2)') "Original Price Tag Before Tax", & 1 Error: Fortran 2008: ‘G0’ in format at (1) in fortran

i am a beginner and trying to learn fortran however i face the following issue , i'm an absolute beginner at this , i really find it challenging
i changed the g0, Iw and I but none work as specified as i saw in previous posts ,thhe same error keeps spawining again and again, b, the f10.2 also doesnt work
**1. below is my code **
`program discount_chart
implicit none
! Declare variables
real :: original_price, discounted_price_cad, discounted_price_usd
real :: max_price, min_price, discount_percent, cad_to_usd_rate
integer :: i
! Prompt user for input
write(*,*) "Enter the minimum price tag (in CAD, ending in .49 or .99):"
read(*,*) min_price
write(*,*) "Enter the maximum price tag (in CAD, ending in .49 or .99):"
read(*,*) max_price
write(*,*) "Enter the discount percentage (e.g. 20 for 20% off):"
read(*,*) discount_percent
write(*,*) "Enter the CAD to USD exchange rate:"
read(*,*) cad_to_usd_rate
! Check validity of input
do while (mod(min_price, 1.0) /= 0.49 .and. mod(min_price, 1.0) /= 0.99)
write(*,*) "Minimum price tag must end in .49 or .99. Please enter again:"
read(*,*) min_price
end do
do while (mod(max_price, 1.0) /= 0.49 .and. mod(max_price, 1.0) /= 0.99)
write(*,*) "Maximum price tag must end in .49 or .99. Please enter again:"
read(*,*) max_price
end do
do while (discount_percent <= 0 .or. discount_percent >= 100)
write(*,*) "Discount percentage must be between 0 and 100. Please enter again:"
read(*,*) discount_percent
end do
do while (cad_to_usd_rate <= 0)
write(*,*) "CAD to USD exchange rate must be positive. Please enter again:"
read(*,*) cad_to_usd_rate
end do
! Print chart header
write(*,'(A,Iw.6,A,F10.2,A,F10.2)') "Original Price Tag Before Tax", &
" Discounted Price After Tax (CAD)", " Discounted Price After Tax (USD)"
! Compute and print discounted prices for each original price in range
do i = 0, 100
original_price = min_price + i * 0.01
if (original_price > max_price) exit
discounted_price_cad = original_price * (100 - discount_percent) / 100 * 1.13
discounted_price_usd = discounted_price_cad / cad_to_usd_rate
write(*,'(F12.8, F12.8, F12.8)') original_price, discounted_price_cad, discounted_price_usd
end do
end program discount_chart`
the error is below
main.f95:41:15:
write(*,'(A,Iw.6,A,F10.2,A,F10.2)') "Original Price Tag Before Tax", &
1
Error: Nonnegative width required in format string at (1)

Why am I getting these errors like Unclassifiable statement at 1 and unexpected junk , etc. in Fortran? [duplicate]

This question already has answers here:
Unclassifiable statement and other errors in an IF in Fortran
(1 answer)
"unclassifiable statement" at if statement [duplicate]
(1 answer)
Closed 2 years ago.
I'm just starting out with Fortran and tried to write a basic program but have been getting tons of errors that I don't understand. Please check the following. I've referred to other such questions but to no avail.
program roots
real a,b,c
real disc
real root1,root2
write (*,*) , "Please provide a, b and c"
read (*,*) ,a,b,c
disc = b**2 -4.0*a*c
if disc < 0
print *,"No real roots"
else if disc = 0
print *,"Equal roots"
root1 = -b/2
print *,"root is :" ,root1
else
print *,"2 real roots"
2*root1 = -b + sqrt(b**2 - 4.0*a*c)
2*root2 = -b - sqrt(b**2 - 4.0*a*c)
print *,"root 1 is:" , root1
print *,"root 2 is:" , root2
end roots
errors:
Error: Unclassifiable statement at (1)
Error: Unexpected junk after ELSE statement at (1)
Error: Unexpected ELSE statement at (1)
Error: Non-numeric character in statement label at (1)
Error: Non-numeric character in statement label at (1)
Error: Expecting END PROGRAM statement at (1)
There were mulitple mistakes in your code.
First of all: always use implicit none otherwise undefined variables might have implicit data types which is hard to debug.
Your if .. end if block had multiple mistakes. Compare both codes.
program roots
implicit none
real a,b,c
real disc
real root1,root2
print *, "Please provide a, b and c"
read (*,*) a,b,c
disc = b**2 -4.0*a*c
if (disc < 0) then
print *, "No real roots"
else if (disc == 0) then
print *, "Equal roots"
root1 = -b/2
print *, "root is :", root1
else
print *,"2 real roots"
root1 = (-b + sqrt(b**2 - 4.0*a*c)) / 2
root2 = (-b - sqrt(b**2 - 4.0*a*c)) / 2
print *, "root 1 is:", root1
print *, "root 2 is:", root2
end if
end program

Fortran Error: Unclassifed Statement in subroutines [duplicate]

I am very new in Fortran and I am stuck with the following program to find roots using quadratic equation.
It is showing the following error:
d = sqrt(bsq \xE2\x80\x93 ac4)
1
Error: Syntax error in argument list at (1)
program quadratic
implicit none
real :: a, b, c, root1, root2
real :: bsq, ac4, d
print *, 'Please enter the coefficients a, b, and c as real numbers'
read *, a, b, c
bsq = b*b
ac4 = 4*a*c
if ( bsq < ac4) then
d = sqrt(bsq – ac4)
root1 = (-b+d)/(2*a)
root2 = (-b+d)/(2*a)
print *, 'The real roots are ', root1, root2
else if ( root1==root2) then
root1 = root2
print *, 'There is one real root which is ', root1
else
print *, 'There are no real roots'
end if
end program quadratic
You need a minus sign between bsq and ac4, not a dash. Look closely.
Minus sign: -
Dash: –

data entrance error Fortran

I'm learning how to programming with fortran90 and i need receive data from a txt file by the command prompt (something like that:
program.exe"<"data.txt).
at the Input txt file I'll always have a single line with at least 6 numbers till infinity.
if the data was wrote line by line it runs fine but as single line I'm receiving the error: "traceback:not available,compile with - ftrace=frame or - ftrace=full fortran runtime error:end file"
*note: i'm using Force fortran 2.0
here is example of data:
0 1 0.001 5 3 1 0 -9 3
edit: just clarifying: the code is working fine itself except for the read statement, which is a simple "read*,". I want know how To read a entire line from a txt once the entrance will be made by the promt command with stream direction.
( you can see more about that here: https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true).
there is no need to read the code, i've posted it just for knowledge.
I'm sorry about the whole inconvenience.
here is the code so far:
program bissecao
implicit none
integer::cont,int,e,k,intc,t1,t2,t3
doubleprecision::ii,is,pre,prec,erro,somaa,somab,xn
doubleprecision,dimension(:),allocatable::co
t1=0
t2=0
t3=0
! print*,"insira um limite inf da funcao"
read*,ii
!print*,"insira o limite superior da func"
read*,is
! print*,"insira a precisÆo admissivel"
read*,pre
if (erro<=0) then !elimina criterio de parada negativo ou zero
Print*,"erro"
go to 100
end if
!print*,"insira a qtd iteracoes admissiveis"
read*,int
!print*,"insira o grau da f(x)"
read*,e
if (e<=0) then ! elimina expoente negativo
e=(e**2)**(0.5)
end if
allocate(co(e+1))
!print*, "insira os coeficientes na ordem:&
! &c1x^n+...+(cn-1)x^1+cnx^0"
read(*,*)(co(k),k=e+1,1,-1)
somab=2*pre
intc=0
do while (intc<int.and.(somab**2)**0.5>pre.and.((is-ii)**2)**0.5>pre)
somab=0
somaa=0
xn =(ii+is)/2
do k=1,e+1,1
if (ii /=0) then
somaa=ii**(k-1)*co(k)+somaa
else
somaa=co(1)
end if
! print*,"somaa",k,"=",somaa
end do
do k=1,(e+1),1
if (xn/=0) then
somab=xn**(k-1)*co(k)+somab
else
somab=co(1)
end if
!print*,"somab",k,"=",somab
end do
if ((somaa*somab)<0) then
is=xn
else if((somaa*somab)>0)then
ii=xn
else if ((somaa*somab)==0) then
xn=(ii+is)/2
go to 100
end if
intc =intc+1
prec=is-ii
if ((((is-ii)**2)**.5)< pre) then
t3=1
end if
if (((somab**2)**.5)< pre) then
t2=1.
end if
if (intc>=int) then
t1=1
end if
end do
somab=0
xn=(ii+is)/2
do k=1,(e+1),1
if (xn/=0) then
somab=xn**(k-1)*co(k)+somab
else
somab=co(1)
end if
end do
100 write(*,'(A,F20.15,A,F20.15,A,A,F20.15,A,F20.15,A,I2)'),"I:[",ii,",",is,"]","raiz:",xn,"Fraiz:",somab,"Iteracoes:",intc
end program !----------------------------------------------------------------------------
In your program, you are using the "list-directed input" (i.e., read *, or read(*,*))
read *, ii
read *, is
read *, pre
read *, int
read *, e
read *, ( co( k ), k = e+1, 1, -1 )
which means that the program goes to the next line of the data file after each read statement (by neglecting any remaining data in the same line). So, the program works if the data file (say "multi.dat") consists of separate lines (as suggested by OP):
0
1
0.001
5
3
1 0 -9 3
But now you are trying to read an input file containing only a single line (say "single.dat")
0 1 0.001 5 3 1 0 -9 3
In this case, we need to read all the values with a single read statement (if list-directed input is to be used).
A subtle point here is that the range of array co depends on e, which also needs to be read by the same read statement. A workaround might be to just pre-allocate co with a sufficiently large number of elements (say 100) and read the data in a single line, e.g.,
integer :: k
allocate( co( 100 ) )
read *, ii, is, pre, int, e, ( co( k ), k = e+1, 1, -1 )
For completeness, here is a test program where you can choose method = 1 or 2 to read "multi.dat" or "single.dat".
program main
implicit none
integer :: int, e, k, method
double precision :: ii, is, pre
double precision, allocatable :: co(:)
allocate( co( 1000 ) )
method = 1 !! 1:multi-line-data, 2:single-line-data
if ( method == 1 ) then
call system( "cat multi.dat" )
read*, ii
read*, is
read*, pre
read*, int
read*, e
read*, ( co( k ), k = e+1, 1, -1 )
else
call system( "cat single.dat" )
read*, ii, is, pre, int, e, ( co( k ), k = e+1, 1, -1 )
endif
print *, "Input data obtained:"
print *, "ii = ", ii
print *, "is = ", is
print *, "pre = ", pre
print *, "int = ", int
print *, "e = ", e
do k = 1, e+1
print *, "co(", k, ") = ", co( k )
enddo
end program
You can pass the input file from standard input as
./a.out < multi.dat (for method=1)
./a.out < single.dat (for method=2)
Please note that "multi.dat" can also be read directly by using "<".

Fortran sqrt () error

I am very new in Fortran and I am stuck with the following program to find roots using quadratic equation.
It is showing the following error:
d = sqrt(bsq \xE2\x80\x93 ac4)
1
Error: Syntax error in argument list at (1)
program quadratic
implicit none
real :: a, b, c, root1, root2
real :: bsq, ac4, d
print *, 'Please enter the coefficients a, b, and c as real numbers'
read *, a, b, c
bsq = b*b
ac4 = 4*a*c
if ( bsq < ac4) then
d = sqrt(bsq – ac4)
root1 = (-b+d)/(2*a)
root2 = (-b+d)/(2*a)
print *, 'The real roots are ', root1, root2
else if ( root1==root2) then
root1 = root2
print *, 'There is one real root which is ', root1
else
print *, 'There are no real roots'
end if
end program quadratic
You need a minus sign between bsq and ac4, not a dash. Look closely.
Minus sign: -
Dash: –