How do I use "i" as an imaginary number in an equation in Objective-C [duplicate] - ios

This question already has answers here:
Are "Complex Numbers" already defined in Objective-C?
(4 answers)
Closed 9 years ago.
Lets say I want to calculate Vout where Vout = (Vin/((I*w*R*C)+1));
where "i" should be defined as the sqrt(-1) . How do I do that in Objective-C?

You can #include <complex.h> then use either _Complex_I or I macros (note the uppercase). The type of variables that contains complex values are denoted with the _Complex attribute, which can also be written simply complex.
double complex c1 = 1.0 + 2.0 * I; // 1+2i
double complex c2 = 2.0 + 3.0 * I; // 2+3i
double complex sum = c1 + c2;
double complex mul = c1 * c2;
You can then use the creal and cimag functions to get real and imaginary parts of a complex.
So in your case:
double Vin = 20; // in Volts
double w = 60; // frequency of your sinusoidal source (60Hz)
double R = 50; // 50 ohms
double C = 20e-6; // 20 µF
double complex invertZc = I*w*C; // Zc = 1/jwC, invertZc = jwC
double complex Vout = Vin / (1. + R*invertZc); // Vout = Vin * 1.0 / (1+Zr/Zc)
Note that all this is provided by the GNU C language (see here), and are not specifically part of Objective-C itself but come from GNU C (Objective-C being a superset of C) and its extensions (which are supported by the GCC and LLVM compilers used by Xcode)

Objective C does not have any built-in facility for handling complex numbers. You have to do the calculations yourself. Create a typedef of a struct imaginaryNumber that contains a real and imaginary part. Write functions that add and multiply those structures and return another one as a result. (To multiply 2 complex numbers (a1+b1i)•(a2+b2i) you treat the numbers as polynomials and use the FOIL method to calculate the result. The product of the 2 imaginary terms becomes a real number because i • i = -1.

Related

A working function but having trouble with a particular float value

This function takes a float then spits out the two integers for the decimal value. At least that was the intention
let flr (x:float) = float(int(x))
let f x =
let r y = let x = x * y in x = flr(x)
let rec f y =
if r(y)
then x*y,y
else f(y+1.0)
f 1.0
f 0.2;;
val it: float * float = (1.0, 5.0)
f 3.14;;
val it: float * float = (157.0, 50.0)
Here is an example where the integers, er will be integers eventually rather, have not been "simplified"
f 0.14;;
val it: float * float = (35.0, 250.0)
Checking the fractional part to be less than .01, as opposed to equaling exactly zero, got around this issue but I don't really like that solution. So I set it back to what you see in the code above. I am using the function below for some of the values that do not simplify though:
let g (x,y) =
let rec f k =
if x/k = flr(x/k)
then g(k)
else f(k-1.0)
and g k =
if y/k = flr(y/k)
then x/k,y/k
else f(k-1.0)
if x < y then f x else f y
Anyway, the main issue is this value:
3.142857143
Homeboy just keeps grinding without stack errors and I'm not sure what I've ran into here. Any clarity would be awesome! Thanks y'all.
Your algorithm is trying to find a rational number to represent a decimal number (represented as a floating point number).
For any input x, you are looking for a number represented as p/q such that x=p/q and you do this by incrementing q, starting from 1 and checking if you can find an integer p to make this work.
This works fine for numbers that have a nice rational representation like 0.2, but it does not work great for numbers like 3.142857 that do not have a simpler rational representation. For 3.142857, you will just keep iterating until you reach 3142857/1000000 (which is technically correct, but not very helpful).
As mentioned in the comments, there are issues caused by the fact that floating-point numbers cannot be precisely compared, but also, iterating like this for 3.142857143 might just take too long.
You can look up better algorithms for finding a rational number for a given decimal. You could also see if you can accept some margin of error. If you do not need a completely precise solution, you could for example change your r test function to something like:
let r y =
let x = x * y
x < flr(x) + 0.0001 && x > flr(x) + 0.0001
This will not give you exactly the same number, but it will likely find a solution that is good enough.

What does the "simd" prefix mean in SceneKit?

There is a SCNNode category named SCNNode(SIMD), which declares some properties like simdPosition, simdRotation and so on. It seems these are duplicated properties of the original/normal properties position and rotation.
#property(nonatomic) simd_float3 simdPosition API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
#property(nonatomic) simd_float4 simdRotation API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
What's the difference between position and simdPosition? What does the prefix "simd" mean exactly?
SIMD: Single Instruction Multiple Data
SIMD instructions allow you to perform the same operation on multiple values at the same time.
Let's see an example
Serial Approach (NO SIMD)
We have these 4 Int32 values
let x0: Int32 = 10
let y0: Int32 = 20
let x1: Int32 = 30
let y1: Int32 = 40
Now we want to sum the 2 x and the 2 y values, so we write
let sumX = x0 + x1 // 40
let sumY = y0 + y1 // 60
In order to perform the 2 previous sums the CPU needs to
load x0 and x1 in memory and add them
load y0 and y1 in memory and add them
So the result is obtained with 2 operations.
I created some graphics to better show you the idea
Step 1
Step 2
SIMD
Let's see now how SIMD does work.
First of all we need the input values stored in the proper SIMD format so
let x = simd_int2(10, 20)
let y = simd_int2(30, 40)
As you can see the previous x and y are vectors. Infact both x and y contain 2 components.
Now we can write
let sum = x + y
Let's see what the CPU does in order to perform the previous operations
load x and y in memory and add them
That's it!
Both components of x and both components of y are processed at the same time.
Parallel Programming
We are NOT talking about concurrent programming, instead this is real parallel programming.
As you can imagine in certain operation the SIMD approach is way faster then the serial one.
Scene Kit
Let's see now an example in SceneKit
We want to add 10 to the x, y and z components of all the direct descendants of the scene node.
Using the classic serial approach we can write
for node in scene.rootNode.childNodes {
node.position.x += 10
node.position.y += 10
node.position.z += 10
}
Here a total of childNodes.count * 3 operations is executed.
Let's see now how we can convert the previous code in SIMD instructions
let delta = simd_float3(10)
for node in scene.rootNode.childNodes {
node.simdPosition += delta
}
This code is much faster then the previous one. I am not sure whether 2x or 3x faster but, believe me, it's way better.
Wrap up
If you need to perform several times the same operation on different value, just use the SIMD properties :)
SIMD is a small library built on top of vector types that you can import from <simd/simd.h>. It allows for more expressive and more performant code.
For instance using SIMD you can write
simd_float3 result = a + 2.0 * b;
instead of
SCNVector3 result = SCNVector3Make(a.x + 2.0 * b.x, a.y + 2.0 * b.y, a.z + 2.0 * b.z);
In Objective-C you can not overload methods. That is you can not have both
#property(nonatomic) SCNVector3 position;
#property(nonatomic) simd_float3 position API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
The new SIMD-based API needed a different name, and that's why SceneKit exposes simdPosition.

Simulate and present normal distribution

My task is to compare different methods of simulating normal distribution. For example, I use following code, to generate 2 vectors, each 1000 values (Box-Muller method):
k=1;
mu=0;
N = 1000;
alpha = rand(1, N);
beta = rand(1, N);
val1 = sqrt(-2 * log(alpha)) .* sin(2 * pi * beta);
val2 = sqrt(-2 * log(alpha)) .* cos(2 * pi * beta);
hist([val1,val2]);
hold on;
%Now I want to make normal distr pdf over hist to see difference
[f,x] = ecdf(mu+sigma*[val1,val2]);
p = normpdf(x,mu, sigma);
plot(x,p*N,'r');
However, it's look very ugly - I can't distinct val1 from val2 and also my pdf doesn't fit histogram well. I think I'm doing something wrong with this pdf, but I don't know what. I found on the Internet different code:
r = rand(1000,2); % 2 cols of uniform rand
%Box-Muller
%n = sqrt(-2*log(r(:,1)))*[1,1].*[cos(2*pi*r(:,2)), sin(2*pi*r(:,2))];
hist(n) % plot two histograms
It looks better, but I don't know how to plot normal distribution pdf over it - method with ecdf cause error.
I'm rather new in Matlab and sometimes I make simple mistakes (like with vector dimensions) but for now I barely can see them.
Can someone help me with above or propose another way to simulate normal random variables and comparision to it (with B-M method or another, just not so complicated)?
I think your plots have different scales, corrected code would look like this:
clear all;
sigma=1; mu=0; N = 1000;
alpha = rand(1, N); beta = rand(1, N);
val1 = sqrt(-2 * log(alpha)) .* sin(2 * pi * beta);
val2 = sqrt(-2 * log(alpha)) .* cos(2 * pi * beta);
vals = [val1,val2];
Nbins = 50; [h,hx] = hist(vals,Nbins);
bar(hx,h*0.5/(hx(2)-hx(1)))
hold on;
%Now I want to make normal distr pdf over hist to see difference
[f,x] = ecdf(mu+sigma*vals);
p = normpdf(x,mu, sigma);
plot(x,p*N,'r');
As mentioned in the comments, quantitative comparison of the distributions requires performing statistical tests (e.g. goodness of fit http://en.wikipedia.org/wiki/Goodness_of_fit)

Rounding when [int] = [float] + [int] (Obj-C, iOS?)

In this case:
float a = 0.99999f;
int b = 1000;
int c = a + b;
In result c = 1001. I discovered that it happens because b is converted to float (specific for iOS), then a + b doesn't have enough precision for 1000.9999 and (why?) is rounded to higher value. If a is 0.999f we get c = 1000 - theoretically correct behavior.
So my question is why float number is rounded to higher value? Where this behavior (or convention) is described?
I tested this on iPhone Simulator, Apple LLVM 4.2 compiler.
In int c = a + b, the integer b is converted to a float first, then 2 floating point
numbers are added, and the result is truncated to an integer.
The default floating point rounding mode is FE_TONEAREST, which means that the result
of the addition
0.99999f + 1000f
is the nearest number that can be represented as a float, and that is the number 1001f. This float is then truncated to the integer c = 1001.
If you change the rounding mode
#include <fenv.h>
fesetround(FE_DOWNWARD);
then the result of the addition is rounded downward (approximately 1000.99993f) and you would get c = 1000.
The reason is that when you add 1000 you get 8 total decimal digits of precision, but IEEE float is only supports 7 digits.

Get a fraction from its decimal number

I am developing a program that solves a system of equations. When it gives me the results, it is like: "x1= 1,36842". I'd like to get the fraction of that "1,36842", so I wrote this code.
procedure TForm1.Button1Click(Sender: TObject);
var numero,s:string;
a,intpart,fracpart,frazfatta:double;
y,i,mcd,x,nume,denomin,R:integer;
begin
a:=StrToFloat(Edit1.Text); //get the value of a
IntPart := Trunc(a); // here I get the numerator and the denominator
FracPart := a-Trunc(a);
Edit2.Text:=FloatToStr(FracPart);
numero:='1';
for i:= 1 to (length(Edit2.Text)-2) do
begin
numero:=numero+'0';
end; //in this loop it creates a string that has many 0 as the length of the denominator
Edit3.text:=FloatToStr(IntPart);
y:=StrToInt(numero);
x:=StrToInt(Edit3.Text);
while y <> 0 do
begin
R:= x mod y;
x:=y;
y:=R;
end;
mcd:=x; //at the end of this loop I have the greatest common divisor
nume:= StrToInt(Edit3.Text) div mcd;
denomin:= StrToInt(numero) div mcd;
Memo1.Lines.Add('fraction: '+IntToStr(nume)+'/'+IntToStr(denomin));
end;
It doesn't work correctly because the fraction that it gives to me is wrong. Could anyone help me please?
Your code cannot work because you are using binary floating point. And binary floating point types cannot represent the decimal numbers that you are trying to represent. Representable binary floating point numbers are of the form s2e where s is the significand and e is the exponent. So, for example, you cannot represent 0.1 as a binary floating point value.
The most obvious solution is to perform the calculation using integer arithmetic. Don't call StrToFloat at all. Don't touch floating point arithmetic. Parse the input string yourself. Locate the decimal point. Use the number of digits that follow to work out the decimal scale. Strip off any leading or trailing zeros. And do the rest using integer arithmetic.
As an example, suppose the input is '2.79'. Convert that, by processing the text, into numerator and denominator variables
Numerator := 279;
Denominator := 100;
Obviously you'd have to code string parsing routines rather than use integer literals, but that is routine.
Finally, complete the problem by finding the gcd of these two integers.
The bottom line is that to represent and operate on decimal data you need a decimal algorithm. And that excludes binary floating point.
I recommend defining a function GreaterCommonDivisor function first (wiki reference)
This is going to be Java/C like code since I'm not familiar with Delphi
let
float x = inputnum // where inputnum is a float
// eg. x = 123.56
Then, multiplying
int n = 1;
while(decimalpart != 0){// or cast int and check if equal-> (int)x == x
x = x * 10;
decimalpart = x % 1;
// or a function getting the decimal part if the cast does work
n *= 10;
}
// running eg. x = 123.56 now x = 12356
// n = 100
Then you should have (float)x/n == inputnum at this point eg. (12356/100 == 123.56)
This mean you have a fraction that may not be simpified at this point. All you do now is implement and use the GCD function
int gcd = GreaterCommonDivisor(x, n);
// GreaterCommonDivisor(12356, 100) returns 4
// therefore for correct implementation gcd = 4
x /= gcd; // 12356 / 4 = 3089
n /= gcd; // 100 / 4 = 25
This should be quick and simple to implement, but:
Major Pitfalls:
Float must be terminating. For example expected value for 0.333333333333333333 won't be rounded to 1/3
Float * n <= max_int_value, otherwise there will be a overflow, there are work around this, but there may be another solutions more fitting to these larger numbers
Continued fractions can be used to find good rational approximations to real numbers. Here's an implementation in JavaScript, I'm sure it's trivial to port to Delphi:
function float2rat(x) {
var tolerance = 1.0E-6;
var h1=1; var h2=0;
var k1=0; var k2=1;
var b = x;
do {
var a = Math.floor(b);
var aux = h1; h1 = a*h1+h2; h2 = aux;
aux = k1; k1 = a*k1+k2; k2 = aux;
b = 1/(b-a);
} while (Math.abs(x-h1/k1) > x*tolerance);
return h1+"/"+k1;
}
For example, 1.36842 is converted into 26/19.
You can find a live demo and more information about this algorithm on my blog.
#Joni
I tried 1/2 and the result was a "division by zero" error;
I correct the loop adding:
if b - a = 0 then BREAK;
To avoid
b:= 1 / (b - a);

Resources