HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Calculator in FORTRAN

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fortrancalculatorstackoverflow

Problem

This is my first step into Fortran. The program aims to provide a simple way of calculating numbers. Just looking for improvements in general.

program Calc
    real :: a, b, additionAnswer, subtractionAnswer, multiplicationAnswer, divisionAnswer
    print *, "George Gibson's Calc"
    print *, "Type the first number: "
    read *, a
    print *, "Type the second number: "
    read *, b
    additionAnswer = a + b
    subtractionAnswer = a - b
    multiplicationAnswer = a * b
    divisionAnswer = a / b
    print *, a, " + ", b, " = ", additionAnswer
    print *, a, " - ", b, " = ", subtractionAnswer
    print *, a, " * ", b, " = ", multiplicationAnswer
    print *, a, " / ", b, " = ", divisionAnswer
    read *
end program Calc

Solution

Functions

A more "Fortrany" way to do this might be to put calculations in their own functions,

program Calc
   implicit none
   ...
    print *, a, " + ", b, " = ", AddTwoNums(a,b)
    print *, a, " - ", b, " = ", SubTwoNums(a,b)
    print *, a, " * ", b, " = ", MultTwoNums(a,b)
    print *, a, " / ", b, " = ", DivTwoNums(a,b)
 contains
    pure function AddTwoNums(a,b) result(c)
       real, intent(in) :: a,b
       real :: c
       c = a + b
    end function AddTwoNums
    ...
 end program


where the ellipses (...) mean I'm skipping over the other details. The pure specifier gives details to the compiler that can optimize/vectorize it in some cases (probably not much it can do here, but for some more complex cases it might be useful).
Output

You might also want to specify formats for the output. Since you're using single-precision, you probably want to output the first 6-7 decimal digits,

print '(f12.6,a3,f12.6,a3,f12.6)', a," + ", b, " = ", AddTwoNums(a,b)


The f12.6 means it's a floating-point type number with 12 total digits and 6 after the decimal, a3 means it is a character string of length 3 (you can make this one simply a and let the compiler figure it out).
Precision

Single precision is nice, but you can do better; and there's a few ways how:

-ISO_FORTRAN_ENV (needs Fortran 2008 or later compiler)

Within this big module is the real32, real64, and real132 types

Kind type parameters to specify a REAL type with a storage size of 32, 64, and 128 bits. It is negative if a target platform does not support the particular kind. (Fortran 2008 or later.)

and would be used as

program Calc
   use iso_fortran_env
   real(kind=real64) :: a, b
   ...


-ISO_C_BINDING (need Fortran 2003 or later compiler)

This module is for improved compatibility with C programs/functions. Within it are C_double and C_long_double types that will match the equivalent C types. This would be used as

program Calc
   use iso_c_binding
   real(kind=c_double) :: a, b
   ...


-Kind specifier (part of the 1990 standard)

This is the default way to specify the precision without useing a module. This is done as

program Calc
   integer, parameter :: wp = selected_real_kind(15,307)
   real(kind=wp) :: a, b
   ...


where wp is typically short for "working precision" (some people choose to append an underscore in case they want to use wp as a variable). The first number in selected_real_kind is the decimal precision and the second number is the exponent range (-307 to +307). You are also not restricted to using integers associated with any particular precision (single or double) here, you can choose to use selected_real_kind(10,40), for instance. Fortran 2003 standards specify that absent values for the precision & radix are assumed to be zero.
Comments

This is general and not specific to Fortran, but I'm a big fan & proponent of comments. Even when it's absolutely trivial & blatantly obvious what is being done on the line below, it benefits you (as practice for the more complex computations) and potential future readers (so that they know what is being done & why).

Code Snippets

program Calc
   implicit none
   ...
    print *, a, " + ", b, " = ", AddTwoNums(a,b)
    print *, a, " - ", b, " = ", SubTwoNums(a,b)
    print *, a, " * ", b, " = ", MultTwoNums(a,b)
    print *, a, " / ", b, " = ", DivTwoNums(a,b)
 contains
    pure function AddTwoNums(a,b) result(c)
       real, intent(in) :: a,b
       real :: c
       c = a + b
    end function AddTwoNums
    ...
 end program
print '(f12.6,a3,f12.6,a3,f12.6)', a," + ", b, " = ", AddTwoNums(a,b)
program Calc
   use iso_fortran_env
   real(kind=real64) :: a, b
   ...
program Calc
   use iso_c_binding
   real(kind=c_double) :: a, b
   ...
program Calc
   integer, parameter :: wp = selected_real_kind(15,307)
   real(kind=wp) :: a, b
   ...

Context

StackExchange Code Review Q#109379, answer score: 4

Revisions (0)

No revisions yet.