Converting Integer to Double Precision in fortran [duplicate] - fortran

This question already has an answer here:
Real value after assignment different from the real expression
(1 answer)
Closed 1 year ago.
I am seeing a strange problem, when I convert a large int to float, the values are not the same,
Here's a test program that replicates the problem
program test
integer a
a = 135000011
b = dble(a)
write(*,*) a, b
end
This prints
135000011 135000012
What is happening? How can I circumvent this?

I have found the error and how to fix this?
Since the value of b is not declared, fortran implicitly assumes its to be real, so to mitigate and correct the issue b should be declared as double precision
full program here
program test
integer a
double precision b
a = 135000011
b = dble(a)
write(*,*) a, b
end
This prints
135000011 135000011.00000

Related

Float value not working as intended unless I add f after the initialization or initialize the variable as double [duplicate]

This question already has answers here:
Is there a functional difference between "2.00" and "2.00f"?
(6 answers)
Is floating point math broken?
(31 answers)
Closed 1 year ago.
When I compile and run the following code, x only gets printed when I initialize float x=1.5. It does not work for other values, for example, when I initialize float x=1.2 and write when(x==1.2), it does not print the value of x.
#include<stdio.h>
int main()
{
float x=1.5;
while (x==1.5)
{
printf("\n%f",x);
x-=1;
}
}
However, when I initialize float x=1.2f and write when(x==1.2f), the code runs as intended.
Also, if I declare and initialize x as double x=1.2, and write printf("\n%lf",x);, the code runs as intended.
This happens in both C and C++.
It tells the computer that this is a floating point number. If there is no f after the number, it is considered a double or an integer (depending on if there is a decimal or not).
3.0f -- float
3.0 -- double
3 -- integer

Double precision in Fortran for trignometric functions [duplicate]

This question already has answers here:
Result of GAMMA underflows its kind
(2 answers)
Is There a Better Double-Precision Assignment in Fortran 90?
(2 answers)
Best practice when working with double precision magic numbers
(1 answer)
Closed 1 year ago.
I am using the following code to calculate cos for pi/2 in Fortran.
program precision_Fortran
IMPLICIT NONE
!!integer, parameter :: dp = kind(1.0d0) !!Gives same result as line below
integer, parameter :: dp = selected_real_kind(15, 307)
Real(dp), parameter:: pi=4.0*atan(1.0)
Real(dp) :: angle
angle = cos(pi/2.0)
write(*,*)'pi = ', pi
write(*,*)'angle = ', angle
end program precision_Fortran
I compiled using gfortran and ftn95. From both, the output is
pi = 3.1415927410125732
angle = -4.3711390001862412E-008
How do I get a better precision for angle here? For instance in C++ I see it in order of E-18, for all declaration using double.
Please let me know if more information is needed to explain it better.
Extra : The main code I am using, with physical equations having trigonometric terms, is having precision issues, and am not entirely sure, but am suspecting it's because of this. So, want to check if above could be improved somehow. Not expert with Fortran so struggling to figure this out.

Floating point math accuracy, c++ vs fortran [duplicate]

This question already has answers here:
Different precision in C++ and Fortran
(2 answers)
Closed 2 years ago.
I have tried to implement a recursive function, in both C++ and Fortran, which calculates the value of the n'th Legendre polynomial, at x. In Fortran I have
recursive function legendre(n, x) result(p)
integer, intent(in) :: n
real(8), intent(in) :: x
real(8) :: p
if(n == 0) then
p = 1.0
else if (n == 1) then
p = x
else
p = (2.0*real(n,dp)-1.0)*x*legendre(n-1,x)-(real(n,dp)-1.0)*legendre(n-2,x)
p = p / real(n,dp)
end if
end function legendre
and then in C++ I have
double legendre(int n, double x) {
double p;
if(n == 0) return 1.0;
else if(n == 1) return x;
else {
p = (2.0*(double)n - 1.0)*x*legendre(n-1,x)-((double)n - 1.0)*legendre(n-2,x);
p /= (double)n;
return p;
}
}
These two functions seem to be exactly the same to me, both using double precission, but the result from the Fortran function is substantial different from the C++ result. For example,
legendre(7,-0.2345) = 0.28876207107499049178814404296875 according to WolframAlpha. The two codes above, when compiled with no optimizations produce
Fortran : 0.28876206852410113
C++ : 0.28876207107499052285
I know that the answers should not be the same due to floating point arithmetic, but the difference in value here for double precision seems somewhat large to me. What is the reason that the Fortran value is so far off from the other two ?
Although the variables in your FORTRAN function are defined as double-precision (8 bytes), the constants you have specified are default (single-precision, 4-byte) values.
According to this discussion, that means the arithmetic is performed to single-precision accuracy:
Even if the variable that you are assigning the result to is defined
to be DP, the Fortran standard requires that the arithmetic on the
constants be performed using SP. That is because you are using default
real constants, since you do not have any kind type parameter at the
end of the constants. By rule, default real is SP.
And, further on in the same discussion:
...Starting with Fortran 90, published in June 1991, this practice of
"promoting" SP constants to DP is prohibited.
So, in order to force double-precision maths, specify the constants as DP: instead of, for example, 1.0, specify 1.0D0 (and so forth for the others).
Thanks to Adrian's response, I was able to fix the problem. Nothing was wrong with the code in the Fortran function, the issue was the value of x which I was passing to it. Even though in the main program, I had defined x as real(8) and latter assigned it the value with a simple
x = -0.2345
which I thought should be double precision. It should actually be
x = -0.2345_dp
This results in the two functions having the same answer. I believe it is likely due to the reason that Adrian pointed out.

Fortran get complex number from a real number.

I am working on writing a Fortran which has to solve square root and that results in getting a complex number, but Fortran doesn't print it or passes that to another variable. It gives (NaN, 0.000).
This is a dummy code to represent the problem that i am having with the actual code i am working on. If you guys can give me any information that would be helpful. Thank You.
program test
IMPLICIT NONE
COMPLEX X
REAL a, b, c
a = 1
b = 1
c = 1
X = sqrt(b - 4*a*c)
print *, REAL(X), ' - j',-AIMAG(X)
end program test
Since a, b and c are all reals, the expression on the right-hand side of the assignment will be calculated in real arithmetic. Assigning it to a complex variable on the left-hand side doesn't change that. If you want the calculation done as a complex value, the easiest way is to declare a, b, and c as complex.

Result of GAMMA underflows its kind

I would like to calculate gamma(-170.1) using the program below:
program arithmetic
! program to do a calculation
real(8) :: x
x = GAMMA(-170.1)
print *, x
end program
but I get the error:
test.f95:4.10:
x = GAMMA(-170.1)
1
Error: Result of GAMMA underflows its kind at (1)
when I compile with gfortran. According to Maple gamma(-170.1) = 5.191963205*10^(-172) which I think should be within the range of the exponent of the variable x as I've defined it.
The below modification of your program should work. Remember that in Fortran the RHS is evaluated before assigning to the LHS, and that floating point literals are of default kind, that is single precision. Thus, making the argument to GAMMA double precision the compiler chooses the double precision GAMMA.
program arithmetic
! program to do a calculation
integer, parameter :: dp = kind(1.0d0)
real(dp) :: x
x = GAMMA(-170.1_dp)
print *, x
end program
-170.0 may be treated as a float. If so, changing it to a double should resolve the issue.