INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Fortran 95 kind conversion

Fortran 95 kind conversion

(OP)
Hello,
I want to convert an integer variable into a selected_real_kind but I am not sure how to do this. Can anyone help me? The code looks like this:

integer, parameter :: rk = selected_real_kind(15,307) !in this case double precision
integer :: a = 10
real(rk) :: b

b = 1._rk/a !here I get zero (integer division)
b = 1._rk/10._rk !here I get 0.1
b = 1._rk/(a)_rk !here I get a compiler error (gfortran)

My question is: what is the equivalent to dble(a) for a general kind conversion?

RE: Fortran 95 kind conversion

Hhhhmmm...I have read about these new precision styles, but refuse to use them...I just find rather convoluted and I don't think I have need for it, so far...oh well.

In any case...

I don't think integer variable a is causing the zero, for as long as the numerator is not integer, a should be promoted.

Try explicit "real(kind=rk)"

Just in case, make sure that your request for rk is being honored, i.e., it is working...if rk is -1, -2 or -3 is not working.

You may want to post a minimal, non-working source for us to take a better look...it could very well be something else in your program that is causing the behavior that you don't like.

RE: Fortran 95 kind conversion

(OP)
You are right, the integer has to be in the numerator, but my question is still the same.
This is a minimal example:

CODE --> fortran

program conversion
  implicit none

  integer, parameter :: rk = selected_real_kind(15,307)
  integer :: a = 10, b = 5
  real(rk) :: c

!integer division but integer output -> works
  c = a/b
  write (*,*) c
!integer division but non integer output -> zero
  c = b/a
  write (*,*) c
!works, but I guess I might lose precision or get a kind mismatch in more complex situations when I set rk to higher precision
  c = dble(b)/a
  write (*,*) c
!this trick seems to work, but I am not too fond of it
  c = 1._rk*b/a
  write (*,*) c

end program conversion 

This code is working, but what I am looking for is a nicer way to write c = 1._rk*b/a, something like c = (b)_rk/a which unfortunately produces a compiler error.

RE: Fortran 95 kind conversion

semmmmml:

Regarding your 4 cases above:
1) it is working, with an integer as immediate result of integral division but promoted upon assignment to real(rk) c variable.
2) it is working, with an integer as immediate result of integral division but promoted upon assignment to real(rk) c variable. Just because the result is zero it does not mean is not working or that it is not integer...0 is the correct answer for integral division of a value divided by a greater one.
3) this works and it is one correct way to avoid integral division when one would otherwise happen due to type of operands.
4) this happens to work but only because the operators have the same priority and, thus, operations executed from left to right; option (3) is better and is clearer regarding awareness and intent.

And, no, you are not loosing precision in any of these cases...you are just not magically gaining any either. When you assign a double precision value to a single precision variable, you loose precision. When you assign a lower precision value to a higher precision variable, you can't magically gain precision and expect the far away decimals to be set correctly...they may be noise...it is only when you truly carry operations with all higher precision values that you can count on all decimals being correctly set.

So, be mindful and try to understand better what you are doing and what all this means.

RE: Fortran 95 kind conversion

(OP)
Hello salgerman,

thank you for your explanation. I understand all the above and of course I understand that I do not gain precision by converting an integer into a real. Actually I just wanted to know, if there was an easy way to convert an integer into a selected_real_kind. This is why i did not put much effort in finding an example where you see the loss of precision. (In the above example you can't see it because real(rk) is the same as real(8).

Let me give you a better example:

CODE --> fortran

program conversion
  implicit none

  integer, parameter :: rk = selected_real_kind(17,307)
  real(rk) :: pi = 3.14159265358979323846264338327950288419716939937510582
  integer :: a = 10, b = 1
  real(rk) :: c

! comparison of dble and rk
  write(*,*) pi
  write(*,*) dble(pi)

!adding 0.1 to pi/10
  c = 0.1_rk + pi/dble(a)
  write(*,*) c

!loss of precision
  c = dble(b)/dble(a) + pi/dble(a)
  write(*,*) c

!step by step to analyse where we made the mistake
  c = dble(b)/dble(a)
  write(*,*) c
  c = c + pi/dble(a)
  write(*,*) c

end program conversion 

Here I lose precision! The digits that exceed the number of digits of double precision seem to be random. I am not sure how to solve this problem, nor if this is compiler dependent. I use gfortran.

RE: Fortran 95 kind conversion

Again...there is no loss of precision on anything that you are showing above. Please explain more clearly with text output and the like, where exactly you see loss of precision.

First of all, you are fooling yourself by assigning to PI a number with that many decimal places...they are being lost right away as your have selected a kind that only guarantees 17 decimal places, in the first place: "selected_real_kind(17,307). Is this clear?

Second, you need to be aware that YOU like working on base 10, yet, you are working on a computer that stores numbers in base 2 !!!...Not every decimal number can be represented in binary and, so, you will notice that a hard coded number that you enter may end up being a slightly different number as soon as it is stored in the computer.

Here is a print out of what I am getting from your program after explicitly specifying output format f30.25 to show that things remain consistent up to 17 significant digits and after that (the blank space) anything goes.

CODE

rk =           10
pi         =    3.1415927410125732 421875000
dble(pi)   =    3.1415927410125732 421875000
0.1+pi/a,c =    0.41415927410125732 42133300
b/a+pi/a,c =    0.41415927410125732 97698700
c=b/a,   c =    0.10000000000000000 55511200
c+=pi/a  c =    0.41415927410125732 97698700 

RE: Fortran 95 kind conversion

(OP)
Yes, I am aware that many of the digits get lost right away, I just copied them in and was too lazy to delete the obsolete ones. And about the output: my mistake! Again, I didn't count the digits and didn't think that write(*,*) prints irrelevant digits. My output looks like this:

CODE -->

3.14159274101257324219
3.1415927410125732
0.414159274101257324213
0.414159274101257329770
0.100000000000000005551
0.414159274101257329770 

As the second output is cut off a few digits earlier and the second last gets random digits there, I assumed this is where I lose information. But, of course, you are right! Up to the 17th digit everything is okay.

BUT... now another things stumbles me: my input for pi is
3.141592 65358979323846
and my output (as well as yours) right away is
3.141592 74101257324219

SEEMS LIKE INFORMATION WAS LOST AT THE 7TH DIGIT HERE ????
I'm confused...

RE: Fortran 95 kind conversion

That I am not 100% sure; but, like I said, this most probably has something to do with decimal vs binary representation.

RE: Fortran 95 kind conversion

(OP)
After doing some digging, I came to the following result:
The cut off after the 7th digit came from not initializing pi correctly
wrong:
real(rk) :: pi = 3.14159265358979323846264338327950288419716939937510582
correct:
real(rk) :: pi = 3.14159265358979323846264338327950288419716939937510582_rk

The first line gives me a real(rk) variable with precision of a real(4)!

Now let's have a look at the program again:

CODE -->

program conversion
  implicit none

  integer, parameter :: rk = selected_real_kind(21,307)
  real(rk) :: pi = 3.14159265358979323846264338327950288419716939937510582_rk
  integer :: a = 10, b = 1
  real(rk) :: c

! comparison of dble and rk
  write(*,*) pi
  write(*,*) dble(pi)

!adding 0.1 to pi/10
  c = 0.1_rk + pi/dble(a)
  write(*,*) c

!loss of precision
  c = dble(b)/dble(a) + pi/dble(a)
  write(*,*) c

end program conversion 

and the result:

CODE -->

!here I get a minimum of 21 decimals although I gain a few because the bits for the exponent are free
   3.14159265358979323846 264338327950280
!here I get a minimum of 15 decimals and gain one decimal because no exponent
   3.14159265358979 31
!the region between the two spaces is the range from 15 to 21 decimals, where I clearly lose precision
  0.414159265358979 323846 264338327950318
  0.414159265358979 329397 379461453732991 

So, I'm sorry, but I have to revoke the statement of my last post. It just looked like we are not losing precision because we lost it right in the beginning and because, in case we don't have an exponent, it is hard to tell exactly how many decimals of precision we will get. 15 and 21 in this case is just the lower limit and those two values seem to be far enough apart to observe the loss of precision.

Thus my question seems to be justified and remains the same:
IS THERE A WAY TO CONVERT AN INTEGER INTO A GENERAL REAL KIND?

RE: Fortran 95 kind conversion


Instead of "dble(a)", try "real(a,kind=rk)"

RE: Fortran 95 kind conversion

(OP)
Thank you, this works! :)

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close