"nan" and "nani" is being displayed in my output. I have discovered that this stands for "not a number", but I am not able to see where I am going wrong, and whether my problem lies with my lack of understanding of Objective-C, or imaginary numbers, or something else.
Any help or pointers would be much appreciated!
Thanks.
#import <Foundation/Foundation.h>
#interface Complex: NSNumber
-(void) setReal: (double) a;
-(void) setImaginary: (double) b;
-(void) print; // display as a + bi
-(double) real;
-(double) imaginary;
#end
#implementation Complex
{
double real;
double imaginary;
}
-(void) setReal: (double) a
{
real = a;
}
-(void) setImaginary: (double) b
{
imaginary = b;
}
-(void) print
{
NSLog (#"%f x %fi = %f", real, imaginary, real * imaginary);
}
-(double) real
{
return real;
}
-(double) imaginary
{
return imaginary;
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
Complex *complex1 = [[Complex alloc] init];
// Set real and imaginary values for first complex sum:
[complex1 setReal: 2];
[complex1 setImaginary: 3 * (sqrt(-1))];
// Display first complex number sum with print method:
NSLog (#"When a = 2 and b = 3, the following equation a x bi =");
[complex1 print];
//Display first complex number sum with getter method:
NSLog (#"When a = 2 and b = 3, the following equation
a x bi = %f x %fi = %fi", [complex1 real], [complex1 imaginary],
[complex1 real] * [complex1 imaginary]);
}
return 0;
}
Your NaNs come from sqrt(-1).
Do you want to implement your own complex types? C99 adds them, so unless you're using an ancient Objective-C compiler you'll be able to do something like this:
#include <complex.h>
double complex c = 3 * 2 I;
double r = creal(c);
double i = cimag(c);
There's some useful documentation and examples in the GNU libc manual: Complex Numbers.
The main problem is here:
[complex1 setImaginary: 3 * (sqrt(-1))];
The result of sqrt(-1) is NaN, sqrt() does not return "complex" numbers in any sense.
To set the imaginary part of your Complex object, you just set
[complex1 setImaginary: 3];
(setImaginary: expects a double argument, which makes sense because the imaginary part of a complex number is a real number.)
Remark: I have no idea what you want to achieve with your print method, but it does not
print a + bi as stated at the top of your program.
Related
** UPDATE **
I have changed the extraneous division by zero error in the reduce method. This was not causing the problem.
Original Question Text
I am in the process of reading Stephen Kochan's book, Programming in Objective-C, 6th Edition. There is a program in Capter 9 (9.1) that demonstrates Polymorphism by having complex numbers and fraction each have a print method and an add method.
resultComplex = [c1 add: c2]
and
resultFraction = [f1 add: f2]
and likewise with the print methods. It is completely understandable to me but there appears to be a bust somewhere in the code and I was hoping someone could help. The book is excellent and previous chapters build on themselves with existing code. The earlier versions of the code have all worked. I am suspecting that I have done something stupid like mis-typed something but I've been pouring over it for a few hours.
The output is as follows:
Chapter_9[5617:303] 18 + 2.5i
Chapter_9[5617:303] +
Chapter_9[5617:303] -5 + 3.2i
Chapter_9[5617:303] -----------
Chapter_9[5617:303] 13 + 5.7i
Chapter_9[5617:303]
Chapter_9[5617:303] 1/10
Chapter_9[5617:303] +
Chapter_9[5617:303] 2/15
Chapter_9[5617:303] ------
(lldb)
The program is able to add the Complex numbers but dies at the point it is required to add the Fractions. Xcode identifies add method in Fraction as the offender the following line as the offensive point:
Fraction *result = [[Fraction alloc] init]; // must be alloc/init here
I will include the class files (.h and .m) for the Fraction class. I am leaving out the Complex class because that part of the code runs fine, although there is an analogous line in that Class that seems to work fine. If it is necessary, I will update the post to add those. I just didn't want to drown everyone with that code if my error is obvious.
UPDATE
I am inserting a picture of the debug and output
Fraction Header File
//
// Fraction.h
// Chapter_9
#import <Foundation/Foundation.h>
#interface Fraction : NSObject
#property int numerator, denominator;
-(void) print;
-(void) setTo: (int) n over: (int)d;
-(double) convertToNum;
-(Fraction *) add: (Fraction *) f;
-(void) reduce;
#end
Fraction Implementation File
//
// Fraction.m
// Chapter_9
#import "Fraction.h"
#implementation Fraction
#synthesize numerator, denominator;
-(void) print
{
NSLog (#"%i/%i", numerator, denominator);
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return NAN;
}
-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}
-(void) reduce
{
int u = numerator;
int v= denominator;
int temp;
while (v!= 0) {
temp = u % v;
u = v;
v = temp;
numerator /= u;
denominator /=u; //originally there was an unrelated error here
}
}
-(Fraction *) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c) / (b*d)
// Store the answer in a new Fraction object called (result)
// ************* Here is where Xcode identifies the error *******************
Fraction *result = [[Fraction alloc] init]; // must be alloc/init here
result.numerator = numerator * f.denominator + denominator * f.numerator;
result.denominator = denominator * f.denominator;
[result reduce];
return result;
}
#end
Program Main File:
//
// main.m
// Chapter_9
// Programming in Objective-C, Stephen Kochan, 6th Edition
//Problem 9.1: Shared Method Names: Polymorphism
#import "Fraction.h"
#import "Complex.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
Fraction *f1 = [[Fraction alloc] init];
Fraction *f2 = [[Fraction alloc] init];
Fraction *fracResult;
Complex *c1 = [[Complex alloc] init];
Complex *c2 = [[Complex alloc] init];
Complex *compResult;
[f1 setTo: 1 over: 10];
[f2 setTo: 2 over: 15];
[c1 setReal: 18 andImaginary:2.5];
[c2 setReal: -5 andImaginary: 3.2];
//add and print 2 complex numbers
[c1 print]; NSLog(#" +"); [c2 print];
NSLog(#"-----------");
compResult = [c1 add: c2]; //compResult is alloc/init in add method
[compResult print];
NSLog(#"\n");
// add and print 2 fractions
[f1 print]; NSLog(#" +"); [f2 print];
NSLog(#"------");
// ******************** Here is where the method call takes place that causes the error
fracResult = [f1 add: f2]; //fracResult is alloc/init in add method
[fracResult print];
}
return 0;
}
I am obviously new to Xcode and Objective-C and so am not able to debug on my own. Sorry for the long and drawn out explanation. I hope someone can help.
Xcode should be giving you a fairly clear division-by-zero error in your reduce method. You haven't copied it correctly from the book, I'm guessing, because your division-by-zero error is being caused by an error in your GCD algorithm.
This:
while (v!= 0) {
temp = u % v;
u = v;
v = temp;
numerator /= u;
denominator /=v;
}
should be this:
while (v!= 0) {
temp = u % v;
u = v;
v = temp;
}
numerator /= u;
denominator /=u;
I'm writing my first real objective C program and it's to make a very simple calculator like in the book Programming in Objective-C 2.0 by Stephen Kochan.
Anyway, whenever I run the program it just continually prints the same thing over and over again, not giving me the option to type anything else. The code is below, and if anyone could help I think the problem is somewhere between the while loop and the switch function. Thank you in advance!
#import <Foundation/Foundation.h>
#interface Calculator : NSObject {
double number, accumulator;
char operator;
}
-(void) add: (double) n;
-(void) subtract: (double) n;
-(void) multiply: (double) n;
-(void) divide: (double) n;
#end
#implementation Calculator
-(void) add: (double) n {
accumulator += n;
NSLog(#"%fl", accumulator);
}
-(void) subtract: (double) n {
accumulator -= n;
NSLog(#"%fl", accumulator);
}
-(void) multiply: (double) n {
accumulator *= n;
NSLog(#"%fl", accumulator);
}
-(void) divide: (double) n {
if (n == 0)
NSLog(#"Error! You can't divide by 0!");
else
accumulator /= n;
NSLog(#"%fl", accumulator);
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
double number, accumulator;
char operator;
Calculator *myCalc = [[Calculator alloc] init];
NSLog(#"Begin calculations by typing a number then S");
scanf("%lf, %c", &accumulator, &operator);
while (operator != 'E') {
NSLog(#"%lf", accumulator);
NSLog(#"What would you like to do next?");
scanf("%lf, %c", &number, &operator);
switch (operator) {
case '+':
[myCalc add: number];
break;
case '-':
[myCalc subtract: number];
break;
case '*':
[myCalc multiply: number];
break;
case '/':
[myCalc divide: number];
break;
default:
break;
}
}
}
return 0;
}
scanf is generally a bad function to use. It's generally better to read an input line into a string and then use sscanf (or some other parser) on the string.
However, the fix in this case is simple. scanf returns the number of input items successfully assigned. You expect two. If there's an error, or end-of-file is reached, it will return less than two. Thus:
int rc = scanf("%lf, %c", &number, &operator);
if (rc < 2) {
break;
}
In short: don't use scanf(). It doesn't work how you think it does.
I'm already tried explaining what's wrong, but basically it doesn't like newlines and stuff and it's pedantic. Search SO for similar questions. The easy solution is to replace scanf() with something actually useful, such as
char buf[0x100];
char *end;
fgets(buf, sizeof buf, stdin);
accumulator = strtod(buf, &end);
while (isspace(*end))
end++;
operator = *end;
Also, your calculator logic is flawed. The myCalc object doesn't share the identically named accumulator variable with the main() function. Your program basically doesn't take into account the first number entered. Also, I don't see what purpose the "type 'S'" part serves, there's absolutely no check for entering "S" in the code, only "E" for end.
On a side note: we're in C (basically), but it's still not a good idea to use C++ keywords as identifiers. Let new and operator be reserved. Call that variable op.
Also, as a design improvement, you can abstract away the big switch statement into the calculator class, and that way you could write something like [myCalc performOp:'+' withNumber:number]; etc.
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;
}
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.
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.)
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 )
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;
}
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;
}
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.
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.)
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 )
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;
}
Hey, working on some categories and I've bumped up against a weird issue, im basically expanding on a calculator class to add some trig methods, and i am getting an incorrect value when i call the sin method in the return in the form of a double. i send a value of 100.7 to the method and it returns 0.168231, from what i can see the correct value should be = 0.939693 or there abouts.
heres the code, I'm also attaching a link to the full project here:
(thanks)
http://files.me.com/knyck2/svpfd4
//
// Calculator_trig.m
// 11.4_calculator_trig
//
// Created by Nicholas Iannone on 1/6/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "Calculator_trig.h"
#import <math.h>
#implementation Calculator (Trigonometry)
-(double) sin
{
double result;
result = (double) sin (accumulator);
return result;
}
-(double) cos
{
double result;
result = cos ( accumulator);
return result;
}
-(double) tan
{
double result;
result = tan ( accumulator);
return result;
}
#end
#import "Calculator.h"
#implementation Calculator
-(void) setAccumulator: (double) value
{
accumulator = value;
}
-(void) clear
{
accumulator = 0;
}
-(double) accumulator
{
return accumulator;
}
-(double) memoryClear
{
memory = 0;
NSLog(#"memory has been cleared");
return accumulator;
}
-(double) memoryStore
{
memory = accumulator;
NSLog(#"memory has been set to %g", memory);
return accumulator;
}
-(double) memoryRecall
{
accumulator = memory;
NSLog(#"accumulator has been set to %g", accumulator);
return accumulator;
}
-(double) memoryAdd
{
memory += accumulator;
NSLog(#"accumulator: %g has been added to memory, memory is now %g", accumulator, memory);
return accumulator;
}
-(double) memorySubtract
{
memory -= accumulator;
NSLog(#"accumulator: %g has been subtracted from memory, memory is now %g", accumulator, memory);
return accumulator;
}
-(double) add: (double) value
{
accumulator += value;
return accumulator;
}
-(double) subtract: (double) value
{
accumulator -= value;
return accumulator;
}
-(double) multiply: (double) value
{
accumulator *= value;
return accumulator;
}
-(double) divide: (double) value
{
accumulator /= value;
return accumulator;
}
-(double) changeSign
{
accumulator = -accumulator;
return accumulator;
}
-(double) reciprocal
{
accumulator = 1 / accumulator;
return accumulator;
}
-(double) xSquared
{
accumulator *= accumulator;
return accumulator;
}
#end
#import <Foundation/Foundation.h>
#import "Calculator.h"
#import "Calculator_trig.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Calculator *myCalc = [[Calculator alloc] init];
double a = 0;
[myCalc setAccumulator: 100.70];
a = [myCalc sin];
NSLog(#" sin of accumulator = %f", a);
[myCalc release];
[pool drain];
return 0;
}
You are computing the sin of 100.7 radians, and the answer given is the correct one.
It's expecting radians. To get the answer you want, convert degrees to radians first:
// [radians] = [degrees] * [pi]/180
double theta = 100.7 * M_PI/180;
// sin(1.757 radians) == ~0.98
double result = sin(theta);
it's expecting radians
According to google, the answer is correct. Notice google assumes radians.
http://www.google.com/search?hl=en&q=sin+of+100.7
The sin function is expecting radian. If you want to get degree you need to convert degree to radian.
How do you do so?
Simple.
In a circle there are 360 degrees. How much radian is there?
Radian is defined as the ratio between the length of the arc in front of the angle divided by the radius.
So, for a full circle, the length of the arc is simply the circumference of the circle.
What is the full circumference of the circle?
Well, π is defined to be the ratio between the circumference of the circle to the diameter.
What is diameter?
Well, diameter is 2 times the radius. Basically diameter is a line that go through the center of the circle and ended when the line meet the circle. Radius is a line that start at a center and end at the circle.
So
Circle's circumference is π * diameter = π * 2 * radius = 2π radius. This is shortened to 2πr, where r is the radius.
So, how many radians are there in a circle?
Easy
You divide the circle's circumference with the radius. Tada you got 2πr/r=2π.
And that 2π is equivalent to 360 degree.
So if we know the degree, how do we know the radian?
Simple, we multiply by 2π and we divide that by 360.
So we multiply the whole thing by 2π/360=π/180.
A way to see this is to imagine that radian and degree are "units". There are π radian for every 180 degrees. That means π radians/180 degrees is one because those are the ratio of the exact same number.
So if you have 107 degree that 107
IS 107 degrees * 1 = 107 degrees * π radians/180 degrees. Of course the computer don't care about the unit. At the end it becomes 107 * π/180.
In Objective-c M_PI is a constant that store the value of π.
What I would do is I would declare
#define radianperdegree (M_PI/180)
Now, the value is not really 1. However, conceptually, radianperdegree is indeed 1 if we take into account the unit. That's because 1 radian is way bigger than 1 degree.
To get the angle in radian, I must not change the angle. What I do is I multiply that by a number that's concepsually 1. So I multiply by radianperdegree. The result is a much smaller number. But that much smaller number represent the exact same angle. That is because that much smaller number is the angle size in radian and each radian is bigger.
Then I do
double result = sin(100.7 * radianperdegree);
Tada.....
Clear?
Another thing you can do is to define
#define RADTODEG(x) ((x) * 57.29578)
#define DEGTORAD(x) ((x) / 57.29578)
And then use sin(DEGTORAD(107))