Fortran get complex number from a real number. - fortran

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.

Related

Converting sensor data (two's complement) to signed integer

I've seen a couple old posts that had a similar context but the answers were code snippets, not explanatory. And I can't even get the code offered in those answers to compile.
I apologize in advance if this is poorly formatted or explained, I am new to C++ and I avoid asking questions on forums at all costs but this has become a real thorn in my side.
I am using C++ to access the memory register of an accelerometer.
This register contains 8 bits of data in the form of twos complement.
The accelerometer is set to have a range of +/- 2 g's, meaning (see section 1.5 of reference manual on page 10)
My goal is to take this twos complement data and save it to a text file as signed base-10 data.
Relevant code below:
while(1)
{
int d = 0;
d= wiringPiI2CReadReg8(fd, DATA_X_H);
d = (int8_t)d;
d = d * EIGHTBITCONV;
std::cout << d << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
I've tested the program by hard coding "d" as 01111111 (127) and the program returns "73". But hard coding "d" as 10000001 (-127) and the program returns the correct "-127".
So the program only functions properly when dealing with negative numbers.
Is this happening because when casting the float "d" to an 8bit integer it truncates the leading zero for positive numbers? How would I fix this?
Link to datasheet: https://www.mouser.com/datasheet/2/348/KX132-1211-Technical-Reference-Manual-Rev-1.0-1652679.pdf
You do not need to convert from 2's complement to "signed integer", because 2's complement is signed integer.
You are only reading 8 bits, but int (the return type of wiringPiI2CReadReg8) has more. So you need a sign-extend conversion. Something like:
int result = (int)(signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
The (int) conversion is implicit and can be omitted. And in your case you are converting to a float (The conversion is again implicit). So:
d = (signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
Actually your solution (negating twice) would work as well. More explicitly it could be written like this (since 1 is int):
d = -((int)(~(int8_t)d) + 1);
But this is just unnecessary work. It could be simplified to be:
d = -(-(int8_t)d);
and now it is obviously simplifies into:
d = (int8_t)d;
same as what I wrote before.
Ok so I think a lot of my confusion came from the fact that I was trying hard code values into my program without proper knowledge of how to do so.
If I were to do hard coding as a method to test the logic, I should have specified that the values of "d" were binary.
So it looks like my original code, while extremely sloppy, was functioning properly.

Converting Integer to Double Precision in fortran [duplicate]

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

Is it necessary to append _kind to number literals in modern Fortran?

This might be stupid question but I'm a bit confused after some recent tests. I always thought the way Fortran deals with reals is the following (modern declaration):
program testReal
implicit none
integer, parameter :: rkind=8
real(kind=rkind) :: a,b,c
// Test 1
a = 1
b = 1.
c = 1._rkind
write(*,"(2(1xES23.15))") a, b, c
// Test 2
a = 1/2
b = 1/2.
c = 1./2.
write(*,"(2(1xES23.15))") a, b, c
// Test 3
a = 3.3
b = 1 * a
c = 1. * a
write(*,"(2(1xES23.15))") a, b, c
end program testReal
Apart from Test 2 - a everything evaulates the same. I always thought I have to put e.g. 1._rkind, 0.5_rkind, etc. after every real in order to make sure to fill the rest of the mantissa with zeros?
Is this just pure luck or is it really not neccessary anymore to attach the _rkind?
Let's look first at Test 1. Here 1, 1. and 1._rkind are literal constants. 1 is an integer of default kind; 1. is a real of default kind; 1._rkind is a real of kind rkind (which could be the same kind as the default). These are all different things.
However, in this case what happens on the assignment is key. As a, b and c are all reals of kind rkind the corresponding right-hand sides are all converted to a real of kind rkind (assuming such a kind has greater precision than default kind). The conversion is equivalent to
a = REAL(1, rkind)
b = REAL(1., rkind)
c = 1._rkind
It just so happens that 1 and 1. are both, in your numeric model, convertable exactly to 1._rkind.
I won't touch on Test 2, as the differences are "obvious".
In Test 3, we have the literal constant 3.3 which is a real of default kind. Again
a = REAL(3.3, rkind)
b = REAL(1, rkind)*REAL(3.3, rkind)
c = REAL(1., rkind)*REAL(3.3, rkind)
due to where and how conversions happen. From this you can see that the results are reasonably the same and the arithmetic happens as real of kind rkind.
What you will notice is a difference
a = 3.3
b = 3.3_rkind
because the (mathematical) real number 3.3 is not exactly representable in your numeric model. And the approximations will differ with real of default kind and kind rkind.
In particular, there is no need to worry about "fill[ing] the rest of the mantissa with zeros".
It is not necessary to specify the kind for numbers which are exactly representable. All integer numbers that are not too big are exactly representable as an IEEE standard floating point number. Therefore it is not necessary for constants like 1. or 3.. Also one half is exactly representable in binary so 1./2. will work fine.
It is necessary for other values, which are not exactly representable, becaause without the suffix the literal is treated as default kind (single precision). In your case 3.3 is NOT exactly representable and you will get different results
write(*,*) 3.3, 3.3_rkind
3.29999995 3.2999999999999998

Another double type trick in C++?

First, I understand that the double type in C++ has been discussed lots of time, but I wasn't able to answer my question after searching. Any help or idea is highly appreciated.
The simplified version of my question is: I got three different results (a=-0.926909, a=-0.926947 and a=-0.926862) when I computed a=b-c+d with three different approaches and the same values of b, c and d, and I don't know which one to trust.
The detailed version of my question is:
I was recently writing a program (in C++ on Ubuntu 10.10) to handle some data. One function looks like this:
void calc() {
double a, b;
...
a = b - c + d; // c, d are global variables of double
...
}
When I was using GDB to debug the above code, during a call to calc(), I recorded the values of b, c and d before the statement a = b - c + d as follows:
b = 54.7231
c = 55.4051
d = -0.244947
After the statement a = b - c + d excuted, I found that a=-0.926909 instead of -0.926947 which is calculated by a calculator. Well, so far it is not quite confusing yet, as I guess this might just be a precision problem. Later on I re-implemented another version of calc() for some reason. Let's call this new version calc_new(). calc_new() is almost the same as calc(), except for how and where b, c and d are calculated:
void calc_new() {
double a, b;
...
a = b - c + d; // c, d are global variables of double
...
}
This time when I was debugging, the values of b, c and d before the statement a = b - c + d are the same as when calc() was debugged: b = 54.7231, c = 55.4051, d = -0.244947. However, this time after the statement a = b - c + d executed, I got a=-0.926862. That being said, I got three different a when I computed a = b - c + d with the same values of b, c and d. I think differences between a=-0.926862, a=-0.926909 and a=-0.926947 are not small, but I cannot figure out the cause. And which one is correct?
With Many Thanks,
Tom
If you expect the answer to be accurate in the 5th and 6th decimal place, you need to know exactly what the inputs to the calculation are in those places. You are seeing inputs with only 4 decimal places, you need to display their 5th and 6th place as well. Then I think you would see a comprehensible situation that matches your calculator to 6 decimal places. Double has more than sufficient precision for this job, there would only be precision problems here if you were taking the difference of two very similar numbers (you're not).
Edit: Unsurprisingly, increasing the display precision would have also shown you that calc() and calc_new() were supplying different inputs to the calculation. Credit to Mike Seymour and Dietmar Kuhl in the comments who were the first to see your actual problem.
Let me try to answer the question I suspect that you meant to ask. If I have mistaken your intent, then you can disregard the answer.
Suppose that I have the numbers u = 500.1 and v = 5.001, each to four decimal places of accuracy. What then is w = u + v? Answer, w = 505.101, but to four decimal places, it's w = 505.1.
Now consider x = w - u = 5.000, which should equal v, but doesn't quite.
If I only change the order of operations however, I can get x to equal v exactly, not by x = w - u or by x = (u + v) - u, but by x = v + (u - u).
Is that trivial? Yes, in my example, it is; but the same principle applies in your example, except that they aren't really decimal places but bits of precision.
In general, to maintain precision, if you have some floating-point numbers to sum, you should try to add the small ones together first, and only bring the larger ones into the sum later.
We're discussing here about smoke. If nothing changed in the environment an expression like:
a = b + c + d
MUST ALWAYS RETURN THE SAME VALUE IF INPUTS AREN'T CHANGED.
No rounding errors. No esoteric pragmas, nothing at all.
If you check your bank account today and tomorrow (and nothing changed in that time) I suspect you'll go crazy if you see something different. We're speaking about programs, not random number generators!!!
The correct one is -0.926947.
The differences you see are far too large for rounding errors (even in single precision) as one can check in this encoder.
When using the encoder, you need to enter them like this: -55.926909 (to account for the potential effect of the operator commutativity effects nicely described in previously submitted answers.) Additionally, a difference in just the last significant bit may well be due to rounding effects, but you will not see any with your values.
When using the tool, 64bit format (Binary64) corresponds to your implementation's double type.
Rational numbers do not always have a terminating expansion in a given base. 1/3rd cannot be expressed in a finite number of digits in base ten. In base 2, rational numbers with a denominator that is a power of two will have a terminating expansion. The rest won't. So 1/2, 1/4, 3/8, 7/16.... any number that looks like x/(2^n) can be represented accurately. That turns out to be a fairly sparse subset of the infinite series of rational numbers. Everything else will be subject to the errors introduced by trying to represent an infinite number of binary digits within a finite container.
But addition is commutative, right? Yes. But when you start introducing rounding errors things change a little. With a = b + c + d as an example, let's say that d cannot be expressed in a finite number of binary digits. Neither can c. So adding them together will give us some inaccurate value, which itself may also be incapable of being represented in a finite number of binary digits. So error on top of error. Then we add that value to b, which may also not be a terminating expansion in binary. So taking one inaccurate result and adding it to another inaccurate number results in another inaccurate number. And because we're throwing away precision at every step, we potentially break the symmetry of commutativity at each step.
There's a post I made: (Perl-related, but it's a universal topic) Re: Shocking Imprecision (PerlMonks), and of course the canonical What Every Computer Scientist Should Know About Floating Point Math, both which discuss the topic. The latter is far more detailed.

what is the command for finding integer in a integer?

for example I have a c++ which takes 2 integers from a file. For example int a = 2052342 and int b = 2. I need to do a search that will search if b is inside a. So in this example, b is inside a, but if b would be for example 7 it wouldn't be. What kind of function, should I use, and could you give me a quick demo of it?
Edit: No it's not a homework, I will compete in Programmers Olympiad this year, so I'm programming all of the C++ exercises that were in last Programmers Olympiads.
You use a pretty flakey example without much explanation of what "if b is inside a' means. Are you just checking to see if the substring of 'int b' is inside 'int a'? if B were 205, or 234, would that count?
Perhaps not the best way, but simple enough, is to convert each integer to a string, and then do a substring check to see if stringB is a substring of stringA.
Update: Infact, when you're parsing your file, i'd just read them in as string, don't even look at this as a problem of integers. You're just doing substring checks. Also, if you parse them as integers, you'd run in to 0-padding being lost.
If you're talking about division or something else, that could be done by doing division.
The simplest answer is just to keep the numbers in their string
representation, and use std::find. If you already have the numbers in
internal format, and converting them to a string would be too expensive:
a % 10 == b will be true if the low digit of a is equal to b, and
a /= 10 will remove the low digit. So:
while ( a != 0 && a % 10 != b ) {
a /= 10;
}
return a != 0;
should do the trick.