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

Converting real*4 to double

fritschen
Beginner
2,966 Views
Is there an easy way to convert a real*4 number to real*8 with the "appended fraction" equal to 0?

Example:
If you code
real(4) :: a
real(8) :: b
a = 125.0
b = dble(a)
then
b = 125.00000762....
or something else.
I want: b = 125.0000000000

Thanks
Ralf
0 Kudos
12 Replies
Steven_L_Intel1
Employee
2,966 Views
The fraction is equal to 0 - binary 0! What you really want is to use 125.0D0 as the constant, which is double-precision. 125.0 is single-precision.

Steve
0 Kudos
durisinm
Novice
2,966 Views
Couldn't you also use 125._8 and get the same result?

Mike
0 Kudos
Steven_L_Intel1
Employee
2,966 Views
You can, yes. But the choice of _8 is implementation-dependent. You could define a PARAMETER constant using SELECTED_REAL_KIND, and a lot of people do it that way, but using D0 works everywhere and is easy to describe. The new way isn't always better!

Steve
0 Kudos
fritschen
Beginner
2,966 Views
Thanks for your replies but I posted the few lines of code only to give an example. In real live I have a lot of code and have to use the variable "a" most of the time as real*4. Only some calculations have to be done in *8. I can't set b to 125d0 but want to have b = a with the fraction (in this case after the 5th digit) to be equal to 00000.
Ralf
0 Kudos
wkramer
Beginner
2,966 Views
The only way I can think of is using an internal write and read. Write the real*4 to a character string and read the real*8 from the character string.
I have tried this method once, but it slowed down the program considerably. I now stick to real*8 only if possible.

Walter Kramer
0 Kudos
david_jones
Beginner
2,966 Views
One way of acheiving this would be to:
(i) multiply by however many thousand it needs;
(ii) convert to integer;
(iii) then convert to double precision;
(iv) finally divide by however many thousand.

You might need to use the new 8-byte integers.

David Jones
0 Kudos
durisinm
Novice
2,966 Views
What would be the appropriate way to do the reverse kind of conversion: converting a double precision number to single precision? Should people use the REAL, FLOAT, or SNGL function?

Is the SNGL function a part of standard Fortran? The Compaq documentation sometimes lists it in black print and sometimes in blue print.

Mike
0 Kudos
Steven_L_Intel1
Employee
2,966 Views
SNGL is standard.

Steve
0 Kudos
NH_Veldhuijzen
Beginner
2,966 Views
Hi,

I often want to do this. My simple solution, which never failed so far, is to set variable b to zero before assigning a to it. I got the output:

1.2500000000E+02
405F400000000000

from this simple program:

program from4to8
real(4) :: a
real(8) :: b
a = 125.0
b=0.d0
b = dble(a)
write (*,'(es16.10/z16)') b,b
end program from4to8

I hope this helps. - Niels -
0 Kudos
NH_Veldhuijzen
Beginner
2,966 Views
After my first reply, I realized this is a serious problem. Programmers should trust that their compilers don't insert unwanted bits into numbers. But... then I saw that it isn't necessarily the compiler that is at fault. For I could not replicate Ralf's results (CVF 6.6A). I tried several statements, even looking at b before it has been assigned a value by me:

program from4to8
real(4) :: a
real(8) :: b
a = 125.0
write (*,'(es16.10,tr4,z16)') b,b ! Not initialised by me
b=a ! Ralf's statements
write (*,*) b
write (*,'(es16.10,tr4,z16)') b,b
b=0.d0
write (*,'(es16.10,tr4,z16)') b,b
b = dble(a)
write (*,'(es16.10,tr4,z16)') b,b
end program from4to8

This is what I got:

0.0000000000E+00 0
125.000000000000
1.2500000000E+02 405F400000000000
0.0000000000E+00 0
1.2500000000E+02 405F400000000000

So, I don't know where Ralf's spurious bit come from. Maybe some obscure option has been cleared inadvertently?
Puzzling. - Niels -
0 Kudos
tlillys
Beginner
2,966 Views
I am encountering a similar problem with 6.6B.

In the following code, the explicit conversion of a real to double for a subtraction is causing some serious problems. And it also appears to be inconsistent. The two cases posed to the subroutine should result in the same difference but they don't and hence the logic path is different.

Any clues as to why?
0 Kudos
Steven_L_Intel1
Employee
2,966 Views
I suggest reading the series "The Perils of Real Numbers" in the CVF Newsletter On the X86 architecture, funny things can happen as intermediate expressions move in and out of registers during optimized code. The optimized results are better, but can be inconsistent. There is an "Enable Floating Point Consistency" option which sometimes improves things (and slows down the code).

In your case, tillys, you really need to read the articles - the values you have can't be represented exactly in binary floating point, and while the differences might seem to be the same when done in decimal, they aren't in fixed-precision binary float.

Steve
0 Kudos
Reply