Fortran behavior of a tiny program - fortran90

I am new in fortran90 (30 minutes ago...) and I have this program:
program example1
implicit none
real (kind=8) :: x,y,z
x = 3.d0
y = 2.d-1
z = x + y
print *, "y = ", y
print *, "x = ", x
print *, "z = ", z
end program example1
but when i run it with:
gfortran example1.f90
./a.out
the output is:
y = 0.20000000000000001
x = 3.0000000000000000
z = 3.2000000000000002
why is not 3.2000000000000000 ???
What I am doing wrong?
Why y has a 1 in last digit?? and why z has a 2 in the last digit??
Sorry if it is a dumb question, but I just dont understand what I am doing wrong...
Thanks!!

There's absolutely nothing wrong with your program. The issue has to do with real's inability to represent decimals precisely, without an error. The problem is that numbers not composed of negative powers of 2 must be represented approximately. That's why there is a small error in the 16-th decimal place. For more information about representation of reals take a look at the article on wikipedia. This is another great article on the same subject.
If you replace 0.2 with 0.25, the problem will go away, because 0.25 is 2 ^ -2.

Related

Solution of the harmonic oscilator using odeint does not match matlab solution

I am solving the harmonic oscilator using odeint and matlab. The equation I am trying to solve is x'' = -x + 0.15*x'. The odeint code can be found here
The exact solution is (per matlab):
S = (exp(-(3*z)/40)*(1591*cos((1591^(1/2)*z)/40) + 3*1591^(1/2)*sin((1591^(1/2)*z)/40)))/1591;
When I run odeint, using this integration method:
{
runge_kutta4< state_type > stepper;
integrate_const( stepper , []( const state_type &x , state_type &dxdt , double t ) {
dxdt[0] = x[1]; dxdt[1] = -x[0] - 0.15*x[1]; }
, x , 0.0 , 10.0 , 0.01 );
}
//]
//[ harm_iterator_const_step]
std::for_each( make_const_step_time_iterator_begin( stepper , harmonic_oscillator, x , 0.0 , 10.0 , 0.01 ) ,
make_const_step_time_iterator_end( stepper , harmonic_oscillator, x ) ,
[]( std::pair< const state_type & , const double & > x ) {
std::cout << x.second << "\t" << x.first[0] << "\t" << x.first[1] << "\n"; } );
//]
I get the following picture for the 10 seconds: odeint
But the graph in matlab is: matlab
I could add the set of data, but as you can see from the picture, even the initial value in the odeint is wrong. It should be 1, but is (according the the code:
| 0 | -0.421912 | 0.246405 |
I have attached the first 0.1 seconds from both solutions to show the big discrepancy between the solutions:
Matlab:
position
1.0000
0.9950
0.9803
0.9560
0.9226
0.8806
0.8304
0.7728
0.7084
0.6378
0.5621
Odeint:
position
-0.421912
-0.419429
-0.416908
-0.414348
-0.411751
-0.409117
-0.406446
-0.403738
-0.400994
-0.398215
-0.395399
I would expect that both applications render similar responses, but I cannot explain why they are so different. The analytical solution shows an exact match with the solver ode45 from matlab, which indicates to me that odeint is doing something weird.
Can someone please help understand the odeint internals so I can use it for my project? Currently, odeint would be an option, but I am sure if I am properly understanding the solution from odeint.
I found my error. In the code that I copied from github, I did not realise that x was called by reference, so everytime I changed integrator, the value of x changed. This value was feeded into the next integator and rather than having fresh values, I gave the wrong values. I had a hiden integrator that I forgot to remove and this was causing the values to changed.
I think, me writing the question, helped me to understand the code I have copied. It was worth the time.

How REST function in Numbers works in Swift

In Apple Numbers the MOD function differs from Swift (in the German version it is REST.
In Numbers:
4,37937=MOD(−1,90373;6,2831)
versus
In swift 3:
let rem1: Double = -1.90373
let rem = rem1.truncatingRemainder(dividingBy: 6.28318530717959)
print(rem)
Prints: -1.90373
What I am doing wrong?
I found the solution:
let rem1: Double = -1.90373
let rem = rem1 - 6.28318530717959 * floor(rem1 / 6.28318530717959)
print(rem)
will do the same like Apples Numbers MOD is doing.
a % b performs the following and returns remainder
a = (b x some multiplier) + remainder
some multiplier is the largest number of multiples of b that will fit inside a.
e.g. some integer constant [0...]
The documentation provides the following as an example
Inserting -9 and 4 into the equation yields:
-9 = (4 x -2) + -1
giving a remainder value of -1.
The sign of b is ignored for negative values of b. This means that a
% b and a % -b always give the same answer.

Find the largest x for which x^b+a = a

Stability (Numerical analysis)
Trying to apply the answer I saw in this question, a+x=a worked just fine with a+eps(a)/2. Suppose we have x^b+a=a, where b is a small integer, say 3 and a=2000. Then a+(eps(a))^3 or a+(eps(a)/2)^3 will always return number a. Can someone help with the measurement of x? Any way, even different from eps will do just fine.
p.s. 1938+(eps(1938)/0.00000000469)^3 is the last number that returns ans = 1.9380e+003.
1938+(eps(1938)/0.0000000047)^3 returns a=1938. Does that have to do with anything?
x = (eps(a)/2).^(1/(b-eps(a)/2))
if b = 3,
(eps(1938)/2).^(1/(3-eps(1938)/2)) > eps(1938)/0.0000000047

Why this output? NSLog(#"%0.2f", 1.345); // output 1.34

**NSLog(#"%0.2f", 1.345); // output 1.34**
NSLog(#"%0.2f", 1.3451);// output 1.35
NSLog(#"%0.2f", round(1.345 * 100)/100.);//output 1.35
Why the first line output 1.34?!!
=======================================
Updated:
NSLog(#"%.2f", round([#"644.435" doubleValue] * 100) / 100); // output 644.43,
but
NSLog(#"%.2f", round([#"6.435" doubleValue] * 100) / 100); // output 6.44?
If I want to convert a NSString to keep two digit after the point, would you please advise how to convert?
Because 1.345 cannot be represented exactly in IEEE754. More than likely, it's something like 1.34444444449 which, when printed, gives you 1.34.
If you search for things like ieee754, precision and floating point, one of the billion or so articles should be able to enlighten you :-)
Look particularly for: What every computer scientist should know about floating point.
Going into a little more detail, examine the following C program:
#include <stdio.h>
int main (void) {
float f = 1.345f;
double d = 1.345;
printf ("f = %.20f\nd = %.20lf\n", f, d);
return 0;
}
The output of this is:
f = 1.34500002861022949219
d = 1.34499999999999997335
So the float value is a little above 1.345 and the double (which is what you get when you specify 1.345 without the f suffix) is a little below.
That explains why you're seeing it truncated to 1.34 rather than rounded to 1.35.

How to get Exponent of Scientific Notation in Matlab

When the numbers are really small, Matlab automatically shows them formatted in Scientific Notation.
Example:
A = rand(3) / 10000000000000000;
A =
1.0e-016 *
0.6340 0.1077 0.6477
0.3012 0.7984 0.0551
0.5830 0.8751 0.9386
Is there some in-built function which returns the exponent? Something like: getExponent(A) = -16?
I know this is sort of a stupid question, but I need to check hundreds of matrices and I can't seem to figure it out.
Thank you for your help.
Basic math can tell you that:
floor(log10(N))
The log base 10 of a number tells you approximately how many digits before the decimal are in that number.
For instance, 99987123459823754 is 9.998E+016
log10(99987123459823754) is 16.9999441, the floor of which is 16 - which can basically tell you "the exponent in scientific notation is 16, very close to being 17".
Floor always rounds down, so you don't need to worry about small exponents:
0.000000000003754 = 3.754E-012
log10(0.000000000003754) = -11.425
floor(log10(0.000000000003754)) = -12
You can use log10(A). The exponent used to print out will be the largest magnitude exponent in A. If you only care about small numbers (< 1), you can use
min(floor(log10(A)))
but if it is possible for them to be large too, you'd want something like:
a = log10(A);
[v i] = max(ceil(abs(a)));
exponent = v * sign(a(i));
this finds the maximum absolute exponent, and returns that. So if A = [1e-6 1e20], it will return 20.
I'm actually not sure quite how Matlab decides what exponent to use when printing out. Obviously, if A is close to 1 (e.g. A = [100, 203]) then it won't use an exponent at all but this solution will return 2. You'd have to play around with it a bit to work out exactly what the rules for printing matrices are.