Являются ли "сложные числа" уже определенными в Objective-C?

Для следующего кода

-Как известно, Objective-C добавить "i" к сложным числам? Когда я определил "реальные" и "мнимые" как двойные значения в файле Complex.m, я понял, что Xcode ТОЛЬКО знает, что "реальный" и "мнимый" являются двойными значениями.

-Если я добавлю "i" в конец сложного числа в файле main.m, например, если я включу "myComplex.imaginary = 7;" в "myComplex.imaginary = 7i;" вывод для этой строки станет 0.00000i, если я добавлю любую другую букву, программа просто не запустится, почему это?

В основном мне кажется, что значение "настоящего" и "мнимого" уже известно Xcode, книга, которую я слежу, не указала это, поэтому я немного смущен.

Кроме того, я должен отметить, что я не создал следующий код, так как сам не мог понять проблему, этот код был скопирован из моего форума книг.

//  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

Сложные типы номеров определены в C99, которая является современной версией Objective-C. Фактический синтаксис похож на:

#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));

Этот суффикс i является расширением исходящим из GCC. Компилятор (clang), используемый Xcode, имеет большинство функций, совместимых с GCC, поэтому вы можете написать 3.4i и не иметь ошибок.


И для ваших вопросов,

  • Как Objective-C знает, чтобы добавить "i" к сложным числам?

Если вы имеете в виду вывод, no Objective-C не знает, чтобы добавить "i" . Он печатает "i" только потому, что вы сказали ему

-(void) print
{
    NSLog(@"%f + %fi", real, imaginary);
//                 ^
}
  • если я включу "myComplex.imaginary = 7;" в "myComplex.imaginary = 7i;" выход для этой линии становится 0.00000i

Поскольку 7i является мнимым числом, а myComplex.imaginary является "двойным", таким образом, действительным числом. В стандарте C рекомендуется, чтобы при преобразовании между реальным и мнимым числами вы получите нуль (C99 §G.4.2/1). Таким образом, эффективно то, что вы написали, myComplex.imaginary = 0.0;.

  • Если я добавлю другую букву, программа просто не запустится, почему это?

На самом деле вы можете писать такие вещи, как 7.0if. Опять же, это C-вещь, адаптированная Objective-C. Вы можете добавить f, чтобы превратить десятичный номер из типа по умолчанию "double" в "float", а GCC добавляет дополнительную функцию, которую вы можете добавить i, чтобы превратить реальный номер в мнимое число, Другие, такие как 7.0x, заставят компилятор остановиться, потому что он не знает, что означает x.

Ответ 2

C99 добавил встроенную поддержку комплексных чисел, поэтому теперь они так же легко обрабатываются, как обычные числа с плавающей запятой или целые числа. Нет более уродливых структур! Предположительно, делая трюки с представлением чисел с плавающей запятой, макрос _Complex_I и эквивалентный I имеют значение, которое при умножении на действительное число приводит к нескольким типам double complex или float complex (complex - это ключевое слово модификатора нового типа, также введенное в C99). Таким образом, благодаря этой новой удобной функции вы можете выполнять вычисления с комплексным числом в C так же легко, как

#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));

Пожалуйста, проверьте объяснение GNU об этом.

Суффикс I является расширением GNU для языка C99, поэтому он нестандартен. Тем не менее, оба компилятора, используемые Xcode (GCC и Clang), реализуют это расширение.

(Sidenote: Xcode знает ничего об этом. Пожалуйста, не путайте IDE с компилятором. Сам Xcode не выполняет компиляцию - компиляторы позади этого делают.)

Ответ 3

Вот класс для работы со сложными числами, которые я разработал для целей моего проекта. Может быть, это будет полезно кому-то. Он содержит стандартные методы сложения, вычитания, умножения и деления. Кроме того, он имеет метод вычисления модуля и аргумента комплексного числа. И, наконец, у него есть метод класса для вычисления коэффициента поворота (сложный показатель), который полезен для алгоритма "бабочки" при работе с быстрым преобразованием Фурье

#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

Спасибо за ваше терпение)

Ответ 4

В классе сложной реализации есть две серьезные ошибки: комплексные числа умножаются и делятся абсолютно неправильно! Абсолютно недостаточно просто умножить или разделить вещественную и мнимую части двух комплексных чисел. Вы должны использовать формулы умножения и деления в этом случае, я думаю, Google содержит много записей об этом. Сейчас это ошибочный код, и его нужно переписать.

Для умножения это должно быть что-то вроде этого

-(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;
}