Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29245 Discussions

Negative exponential should be compiler error - instead gives wrong answer

caplanr
New Contributor I
19,771 Views

Hi,

A colleague of mine noticed a bad behavior of IFX (and IFORT) for Fortran regarding negative exponents without parenthesis.  

From our understanding, the Fortran standard does not allow this:

program negative_exponent
  write(*,*) '10.0**-2 * 2=', 10.0**-2 * 2
end program negative_exponent

However, the above code compiles and runs using gfortran, nvfortran, ifort, and ifx.

On gfortran, it gives a warning about the syntax but then "does the right thing":

```
> gfortran negative_exponent.f90
negative_exponent.f90:2:37:

    2 |   write(*,*) '10.0**-2 * 2=', 10.0**-2 * 2
      |                                     1
Warning: Extension: Unary operator following arithmetic operator (use parentheses) at (1)
> a.out
 10.0**-2 * 2=   1.99999996E-02
```

Using NVIDIA's nvfortran, there is no warning but the code gives the right answer:

```
> nvfortran negative_exponent.f90
> a.out 
 10.0**-2 * 2=   2.0000000E-02
```

However, on ifort or ifx, there is no warning and gives the wrong answer:

```
> ifx negative_exponent.f90
> a.out
 10.0**-2 * 2=  9.9999997E-05
```

It seems to me that this code should ideally throw a compiler error since it is not allowed in Fortran (maybe have a flag to ignore the error?).

However, if it IS going to be allowed, it should give the right answer following standard math PEMDAS in compilation.

 

 - Ron

69 Replies
caplanr
New Contributor I
918 Views

We make this module:

 
module number_types
  use iso_fortran_env
  integer, parameter :: r_typ = REAL64
end module
 
Then always use things like  pi=3.1415926535897932384626433832795_r_typ in the code to ensure precision.
 
I am pretty sure this is compiler independent (absent special flags) since it uses the iso_fortran_env.

 

 
 - Ron
0 Kudos
andrew_4619
Honored Contributor III
646 Views

If you do not put the kind on a real constant the Fortran rules are clear. The constant will be evaluated at the default precision (32bit in this case)  which in the examples above would truncate decimal places and then it would  promote it to a 64 bit real in effect adding a load of trailing zeros. A mistake that many make!

0 Kudos
GVautier
New Contributor III
811 Views

_8 do the same as d0 it promotes the constant to double.

0 Kudos
Steve_Lionel
Honored Contributor III
402 Views

@GVautier wrote:

_8 do the same as d0 it promotes the constant to double.


Please do not hardcode specific kind values! See Doctor Fortran in "It Takes All KINDs" - Doctor Fortran

0 Kudos
Kevinf123
Beginner
82 Views

Hello

 I am not getting this point:

 

program negative_exponent write(*,*) '10.0**-2 * 2=', 10.0**-2 * 2 end program negative_exponent.

 

Can someone please guide me about this regard?

Thanks

0 Kudos
JohnNichols
Valued Contributor III
77 Views

Kevin:

Main point, the use of () is highly recommended, so a maintainer in 30 years can understand your intention. 

Fortran unlike LISP allows us the freedom to use the equation format rules but these can be hard for a compiler to pick up all of the variations, hence someone like me prefers Lisp for readability and FORTRAN for brute speed. 

Do not do this at all.  

Use

variables

a = -2

b = 10

c = 2

(b**a)*c == no chance the compiler will misunderstand you and neither will I + you can create a function and reuse the equation, which with recursion is the beauty of LISP.  MIT taught programming with LISP for many years and the Sussman textbook covers a lot of good crap. 

If you have a Finite Element Program like ULARC it is easy to propagate an equation error and unless you are careful to check that the results match hand answers you can be in for a world of hurt. 

I have this problem with FEM in just comparing the answers - for instance one of the large German FEM programs has an error in one of the major equations.  

 

 

0 Kudos
Arjen_Markus
Honored Contributor II
49 Views

The point is that Fortran does not allow two (or more) operators next to each other. In this case: ** and -. Some languages consider the minus sign to be part of the number, but that is not the case in Fortran. The Intel compiler has a long history and at some point in that history this misuse was allowed with some particular interpretation. But as evidenced in this thread, the interpretation may not coincide with the human interpretation. 

Conclusion: use parentheses or any of the other suggested solutions.

Reply