可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
For the following code,
-How does Objective-C know to add an "i" to complex numbers? When I defined "real" and "imaginary" as double values in the Complex.m file I figured Xcode would ONLY know that "real" and "imaginary" are double values.
-If I add an "i" to the end of a complex number in main.m file, for example, if I turn "myComplex.imaginary = 7;" into "myComplex.imaginary = 7i;" the output for that line becomes 0.00000i, if I add any other letter, the program will simply not run, why is this?
Basically it appears to me that the meaning of "real" and "imaginary" are already known to Xcode, the book I'm following did not specify this so I'm a little confused.
Also, I should note that I did not create the following code as I couldn't figure out the problem on my own, this code was copied from a member of my books forum.
// Complex.h
#include <Foundation/Foundation.h>
@interface Complex : NSObject
@property double real, imaginary;
-(void) print;
-(Complex *) add: (Complex *) complexNum;
-(Complex *) subtract: (Complex *) complexNum;
-(Complex *) multiply: (Complex *) complexNum;
-(Complex *) divide: (Complex *) complexNum;
@end
// Complex.m
#import "Complex.h"
@implementation Complex
@synthesize real, imaginary;
-(void) print
{
NSLog(@"%f + %fi", real, imaginary);
}
-(Complex *) add: (Complex *) complexNum
{
Complex *result = [[Complex alloc]init];
result.real = real + complexNum.real;
result.imaginary = imaginary + complexNum.imaginary;
return result;
}
-(Complex *) subtract: (Complex *) complexNum
{
Complex *result = [[Complex alloc]init];
result.real = real - complexNum.real;
result.imaginary = imaginary - complexNum.imaginary;
return result;
}
-(Complex *) multiply: (Complex *) complexNum
{
Complex *result = [[Complex alloc]init];
result.real = real * complexNum.real;
result.imaginary = imaginary * complexNum.imaginary;
return result;
}
-(Complex *) divide: (Complex *) complexNum
{
Complex *result = [[Complex alloc]init];
result.real = real / complexNum.real;
result.imaginary = imaginary / complexNum.imaginary;
return result;
}
@end
//
// main.m
// Complex
#include <Foundation/Foundation.h>
#import "Complex.h"
int main(int argc, const char *argv[]) {
@autoreleasepool {
Complex *myComplex = [[Complex alloc]init];
Complex *totalComplex = [[Complex alloc]init];
Complex *yourComplex = [[Complex alloc]init];
myComplex.real = 5.3;
myComplex.imaginary = 7;
[myComplex print];
NSLog(@"+");
yourComplex.real = 2.7;
yourComplex.imaginary = 4;
[yourComplex print];
NSLog(@"=");
totalComplex = [myComplex add: yourComplex];
[totalComplex print];
}
return 0;
}
回答1:
Complex number types are defined in C99, which the modern version of Objective-C is a superset of. The actual syntax is like:
#include <complex.h>
...
complex double z = 2.7 + 3.4*I;
complex double w = 4.5 - 1.7*I;
complex double t = z*w;
printf("%g + %gi", creal(t), cimag(t));
That i
suffix is an extension coming from GCC. The compiler (clang) used by Xcode has most features being compatible with GCC, thus you can write 3.4i
and have no errors.
And for your questions,
- How does Objective-C know to add an "i" to complex numbers?
If you mean the output, no Objective-C does not know to add an "i". It prints the "i" only because you told it to
-(void) print
{
NSLog(@"%f + %fi", real, imaginary);
// ^
}
- if I turn "myComplex.imaginary = 7;" into "myComplex.imaginary = 7i;" the output for that line becomes 0.00000i
Because 7i is an imaginary number, and myComplex.imaginary
is a "double", thus a real number. The C standard recommends that, when converting between real and imaginary numbers, you'll get zero (C99 §G.4.2/1). Thus effectively what you've written is myComplex.imaginary = 0.0;
.
- if I add any other letter, the program will simply not run, why is this?
Actually you can write things like 7.0if
. Again, this is a C thing, which Objective-C has adapted. You are allowed to add an f
to turn a decimal number from the the default type "double" to "float", and GCC adds an extra feature that you can add an i
to turn a real number to an imaginary number. Other suffices like 7.0x
will cause the compiler to stop because it doesn't know what x
means.
回答2:
C99 has added native support for complex numbers, so now they are as easy to handle as ordinary floating-point or integer numbers. No more ugly structs! Presumably by doing tricks with the floating-point representation of numbers, the _Complex_I
and the equivalent I
macro have a value that, when multiplied by a real number, results in a number of type double complex
or float complex
(complex
is a new type modifier keyword, also introduced in C99). So with this new convenience feature, you can perform complex-number calculations in C as easily as
#include <complex.h>
double complex z1 = 2.0 + 3.0 * I;
double complex z2 = 1.5 - 2.0 * I;
double complex prod = z1 * z2;
printf("Product = %f + %f\n", creal(prod), cimag(prod));
Please check the GNU explanation about this as well.
The i
suffix is a GNU extension to the C99 language, therefore it's non-standard. Nevertheless, both compilers used by Xcode (GCC and Clang) implement this extension.
(Sidenote: Xcode knows nothing about this. Please don't confuse the IDE with the compiler. Xcode itself doesn't perform compilation - the compilers behind it do.)
回答3:
Here is class for operating with complex numbers I've developed for the purposes of my project. May be it will be useful to somebody. It contains standard addition, subtraction, multiplication and division methods. Moreover it has method for calculating modulus and argument of complex number. And, at last, it has class method for calculating turning factor (complex exponent) that is useful for "butterfly" algorithm when deal with fast Fourier transformation
#import <Foundation/Foundation.h>
@interface Complex : NSObject
@property double re, im;
-(Complex *)add :(Complex *) n;
-(Complex *)sub :(Complex *) n;
-(Complex *)mul :(Complex *) n;
-(Complex *)div :(Complex *) n;
+(Complex *)wkn :(int) k :(int) n;
-(double)mod;
-(double)arg;
@end
#import "Complex.h"
@implementation Complex
@synthesize re, im;
// Addition of two complex numbers
-(Complex *)add:(Complex *)n
{
Complex *res = [[Complex alloc]init];
res.re = re + n.re;
res.im = im + n.im;
return res;
}
// Subtraction of two complex numbers
-(Complex *)sub:(Complex *)n
{
Complex *res = [[Complex alloc]init];
res.re = re - n.re;
res.im = im - n.im;
return res;
}
// Multiplication of two complex numbers
-(Complex *)mul:(Complex *)n
{
Complex *res = [[Complex alloc]init];
res.re = re * n.re - im * n.im;
res.im = re * n.im + im * n.re;
return res;
}
// Division of two complex numbers
-(Complex *)div: (Complex *)n
{
Complex *res = [[Complex alloc]init];
double A = (pow(n.re, 2.0) + pow(n.im, 2.0));
res.re = (re * n.re - im * n.im) / A;
res.im = (im * n.re - re * n.im) / A;
return res;
}
// Modulus of complex number
-(double)mod
{
double res = sqrt(pow(re, 2.0) + pow(im, 2.0));
return res;
}
// Argument of complex number
-(double)arg
{
double res; int quad;
if (re == 0 && im > 0) res = M_PI_2;
else if (re == 0 && im < 0) res = 3 * M_PI_2;
else
{
if (re > 0 && im >= 0) quad = 1;
else if (re < 0 && im >= 0) quad = 2;
else if (re < 0 && im < 0) quad = 3;
else if (re > 0 && im < 0) quad = 4;
double temp = atan(im / re);
switch (quad)
{
case 1:
res = temp;
break;
case 4:
res = 2 * M_PI + temp;
break;
case 2: case 3:
res = M_PI + temp;
break;
}
}
return res;
}
// Turning factor calculation for "butterfly" FFT algorithm
+(Complex *)wkn:(int)k :(int)n
{
Complex *res = [[Complex alloc]init];
res.re = cos(2 * M_PI * k / n);
res.im = -sin(2 * M_PI * k / n);
return res;
}
@end
Thanks for your patience )
回答4:
There are two serious mistakes in class Complex implementation - complex numbers are multiplied and divided in absolutely wrong way! It's absolutely not enough simply multiply or divide real and imaginary parts of two complex numbers. You have to use multiplication and dividing formulas in that case, I think Google contains a lot entries about it. Right now it is erroneous code and it have to be rewritten.
For multiplication it must be something like this
-(Complex *)mul:(Complex *)n
{
Complex *res = [[Complex alloc]init];
res.re = re * n.re - im * n.im;
res.im = re * n.im + im * n.re;
return res;
}