E**x taylor series

Hi all,

I have implemented exercise above in fortran:

Any suggestions about my coding style or pros and cons?

1 Like

Hi @ELNS
in the function fact(n), you could write:

integer, intent(in) :: n
integer :: i

The advantage is that if you make a programming error which modifies n accidentally (imagine you have written do n = 2, i), the compiler will print that kind of error:

Error: Dummy argument ‘n’ with INTENT(IN) in variable definition context (assignment) at (1)

And personally I would not indent the else if(n==0) then and else lines. My eye could not see immediately and clearly the structure of the algorithm.

In the main program, why putting the i==1 case into the loop ?

1 Like

Thank you for you valuable tips :pray: :pray: :pray:

As you can see in the example above, the first and second elements of the series are 1 and x itself. I assigned 1.0 to the sum variable by default and then added up value of x itself to sum value in if (i == 1) section of the main program.

As a general rule of thumb, you should always use optional statements like intent, implicit none, etc. I guess they are optional only for historical reasons, for the compatibility of old code.

Don’t think you lose your time by typing such things: it helps the compiler, and by helping the compiler you are helping yourself. You will save your time (you know, searching a stupid error for 20 minutes…) on the long term.

The compiler can also help you if you add some flags. For example, my favorite flags in gfortran are:

$ gfortran -Wall -Wextra -std=f2003 -pedantic my_program.f90

And if you have several compilers, it can be interesting to compile your program with them. Sometimes a compiler will warn you about something that does not bother the others.

2 Likes

Computing a quotient where the numerator and denominator can both become very large (and possibly overflow) is numerically not recommended.

Writing a program to compute something already available as a built-in intrinsic seems unnecessary. But as a training exercise to learn how to compute other functions expressed as a series, it might be OK.

Here is an alternate version that avoids computing factorials.

program main
  implicit none
  real(8) :: x, add, e2x
  integer(8) :: n, i

  print *, "Enter x"
  read *, x

  n = 2
  add = x
  e2x = 1. + x

  do
     add = add*x/n
     e2x = e2x + add
     if (abs(add/e2x) < tiny(1.0_8)) exit
     n = n + 1
  end do

  print *, n, e2x, exp(x)

end program main

The test (using tiny) is probably too extreme. You might want to explore a more efficient test.

3 Likes

Welcome, Bill! :slight_smile:

@ELNS Nice work, keep it up!

I suggest not naming variables using names of intrinsic procedures or other language entities. If you haven’t already, you’ll notice that Fortran has no reserved words like Fortran does. In your program, you use the name sum for a local variable, and your IDE gave you a hint. In general this is fine and doesn’t break your program, but it:

  1. Precludes you from using the sum intrinsic in the same scope. This may not be an issue if you don’t intend to use it, but if you find out that you do need it in the same scope, then you’ll need to go back and rename all references to your variable.
  2. May confuse the reader of your code–other people or your future self.

Some alternative names could be total, sum_of_elements, summ, or similar.

2 Likes

Hi @ELNS, please consider the following regarding the coding style:
In your main program you initialize some variables at declaration e.g. integer :: i = 1, this is bad practice. It implies the save attribute. In your particular example, there is no side effect, but if you use it inside functions/subroutines or modules it will result in different behavior than expected. As a rule of thumb initialize at declaration if it is a constant variable e.g. integer, parameter :: i = 1 or in case you intentionally need the save attribute, then explicitly declare it like integer, save :: i = 1.

A couple of side-notes: It is better to use markdown to post your code instead of a picture, therefore if you need people to help you by testing your code to be as easy as copy-pasting, it is a lot of time-wasting to rewrite one’s code by looking at a picture. Finally, this post belongs to #help (if a moderator could move it).

3 Likes

Thanks @stavros, I just moved it to “help”.

1 Like

I understand where you’re coming from but I think it’s a stretch to call it bad practice. In functions and subroutines, of course. In programs and modules, it’s perfectly fine to initialize on declaration and I do so in my book. Rather than hiding the caveats of implied save, I prefer to teach it and make clear how it works head-on and early on. I think every Fortran programmer should learn how implied save works and when they can safely initialize on declaration.

3 Likes

I personally also do not recommend to use integer :: i = 1. It leads to problems, for example you cannot just copy the code to make it a subroutine, etc. See this issue for a thorough discussion how to fix this in Fortran itself: https://github.com/j3-fortran/fortran_proposals/issues/40, unfortunately so far we haven’t found a solution where everybody would agree.

3 Likes

@milancurcic I have to insist that this is a bad practice. Let me elaborate. More often than not, you get new-comers to Fortran from other languages, or new-programmers all together, who are not aware of this behavior. If I receive a code, to work on it (review, modify, maintain… etc) from someone that I am not sure of their level of expertise and see initialization at declaration, I will be alarmed, to say the least. On the other hand, if an inexperienced Fortran programmer receives a code with a few variables initialized at declaration without the save attribute, they will think no more of this, with a high chance of misusing it. If, however, there was the save attribute, it would have caught their attention, and probably they would be looking for this feature online.

@certik I read (most) of the issue you linked. I have to admit that I do not understand all this hate the save attribute gets. It can be considered as the equivalent of static in C/C++, I never heard of the C-community complaining about static, why do we? The problem is not with the use of save, rather with its misuse or its no-use that lies on the Fortran design which allows integer :: i = 1 and integer, save :: i = 1 to have the same effect, and unfortunately I do not see an easy way to fix this without breaking backward compatibility. For that reason, and until a permanent solution is given, I consider it a good practice to explicitly use save or never initialize on declaration.

3 Likes

@stavros we are in agreement. I don’t see any hate for the save attribute. What people don’t like is that integer :: i = 1 implies the save attribute. And as you also noted, and as is discussed in that issue at length, there is no easy fix for that, every proposal that was suggested there has some drawbacks.

3 Likes

@vmagnin @longb @milancurcic @stavros @certik
Thank you all for helping me :pray:

2 Likes