Complex numbers не такі вже й складні.
Просто їм потрібна назва, яка не так лякає.
Вони настільки корисні, особливо в інженерії та науці, що R включає комплексні числа як стандартні атомарні типи поряд із цілими числами, числами з плаваючою комою, логічними значеннями, символами та raw.
Число типу complex у R - це одне значення.
Однак у роботі його можна уявляти як пару чисел.
Їх називають «дійсною» та «уявною» частинами, з нещасливих історичних причин.
І знову ж таки, краще зосередитися на простоті, що лежить в основі, а не на дивних назвах.
Щоб створити комплексне число з двох дійсних чисел, достатньо додати суфікс i до уявної частини.
2+3i
#> [1] 2+3i
typeof(2+3i)
#> [1] "complex"
Але щоб створити комплексне число з дійсних змінних, наведений вище синтаксис не спрацює.
Запис r + imi збиває парсер із пантелику, і він вважає imi назвою (неіснуючої) змінної.
Можна або помножити уявну частину на 1i, або скористатися функцією [complex()][ref-complex]:
r <- 2
im <- 3
r + im * 1i
#> [1] 2+3i
# must include the `real` and `imaginary` keywords
complex(real = r, imaginary = im)
#> [1] 2+3i
Можливо, виникає питання: чому i, а не j?
Більшість інженерів віддають перевагу j.
Більшість науковців і математиків віддають перевагу математичному позначенню i для уявної частини, але це позначення конфліктує з використанням i на позначення струму в електротехніці.
У R обрали i, у Python - j, а в Julia оминули суперечку, обравши im.
Варто бути уважними, перемикаючись між мовами програмування [STEM][wiki-STEM].
Щоб отримати частини комплексного числа окремо:
z <- 2+3i
Re(z) # real part
#> [1] 2
Im(z) # imaginary part
#> [1] 3
Будь-яка з частин може дорівнювати нулю, і тоді математики можуть казати, що число «цілком дійсне» або «цілком уявне». Однак у R це все одно комплексне число.
1.2 + 0i
#> [1] 1.2+0i
typeof(1.2 + 0i)
#> [1] "complex"
2i
#> [1] 0+2i
typeof(2i)
#> [1] "complex"
Можливо, ви чули, що «i (або j) - це квадратний корінь із -1».
Поки що це означає лише те, що уявна частина за означенням задовольняє таку рівність:
1i * 1i == -1 # more precisely, 1i * 1i == -1 + 0i
#> [1] TRUE
Це проста ідея, але вона веде до цікавих наслідків.
Більшість операторів, які використовуються з числами з плаваючою комою та цілими числами, також працюють із комплексними числами:
z1 = 1.5 + 2i
z2 = 2 + 1.5i
z1 + z2 # addition
#> [1] 3.5+3.5i
z1 * z2 # multiplication
#> [1] 0+6.25i
z1 / z2 # division
#> [1] 0.96+0.28i
z1^2 # exponentiation
#> [1] -1.75+6i
2^z1 # another exponentiation
#> [1] 0.518895+2.780422i
Більшість математичних функцій працюють із комплексними вхідними даними.
Окрім Re() та Im(), є кілька функцій, особливо дотичних до комплексних чисел.
Conj() просто змінює знак уявної частини комплексного числа (з + на - або навпаки).
abs(<complex number>) гарантовано повертає дійсне число без уявної частини (його «модуль»), а Mod(<complex number>) - це синонім.Arg(<complex number>) повертає фазовий кут у радіанах.z1
#> [1] 1.5+2i
abs(z1)
#> [1] 2.5
Mod(z1) # same as previous
#> [1] 2.5
Conj(z1) # flip sign
#> [1] 1.5-2i
Arg(z1)
#> [1] 0.9272952
Нас щойно найняли в нову службу таксі, яка намагається вирізнитися серед інших пропозицій на вже насиченому ринку. Щоб цього досягти, генеральний директор вирішив запустити в Мангеттені ультрарозкішний сервіс із помічниками на кожному перехресті, які допомагають клієнтам до та після поїздки. Тепер нам потрібно написати трохи коду, який допоможе з роботою сервісу.
Генеральний директор вирішив, що оскільки вулиці Мангеттена розташовані переважно у вигляді сітки, для позначення перехресть вулиць зручно використовувати комплексні числа. У цьому поданні додатні та відʼємні дійсні числа позначають схід і захід, а додатні та відʼємні уявні числа - північ і південь відповідно.
Оскільки створити комплексне число в R трохи, гм... незвично, нам доручили реалізувати функцію простого комплексного числа.
Реалізуйте функцію simplex(a, b), яка приймає цілі числа a і b.
Поверніть комплексне число a+bi.
simplex(1, 1)
#> 1+1i
simplex(-3, 4)
#> -3+4i
Коли клієнт називає перехрестя призначення, водії отримують напрямок, як туди дістатися. Цей напрямок подається у вигляді комплексного числа, де дійсна частина показує, скільки кварталів проїхати на північ чи південь, а уявна частина - відстань на схід чи захід. Щоб узгодити це з канонічним компасом, керівник проєкту вирішив, що північ відповідає додатному уявному напрямку, а південь - відʼємному уявному напрямку. Так само схід відповідає додатному дійсному напрямку, а захід - відʼємному дійсному напрямку.
Реалізуйте функцію driver_directions(start, end), яка приймає координати початкового перехрестя start і координати перехрестя призначення end.
Поверніть комплексне число, яке показує, скільки кварталів на схід/захід і на північ/південь має проїхати водій.
driver_directions(0+0i, 7+5i)
#> 7+5i
driver_directions(-2+3i, 4-5i)
#> 6-8i
З клієнта беруть плату за відстань, яку має подолати таксі. Оскільки вулиці Мангеттена розташовані у вигляді сітки, таксі можуть їздити лише цими маршрутами. Така структура змушує вимірювати відстань уздовж ліній сітки. Відстань можна знайти, додавши кількість пройдених ліній або кількість досягнутих перехресть (тобто не враховуючи початкове перехрестя). Цей показник зазвичай називають мангеттенською відстанню, або нормою L1.
Реалізуйте функцію manhattan(start, end), яка приймає перехрестя start і end.
Поверніть мангеттенську відстань між перехрестями start і end.
manhattan(0+0i, 3+4i)
#> 7
manhattan(-2-3i, -1+1i)
#> 5
Генеральному директору вдалося залучити інвестиційні банки, наголосивши, що сервіс не лише ультрарозкішний, а й екологічний, адже він використовуватиме дресированих ворон, щоб переправляти повідомлення між помічниками на перехрестях (які передають інформацію про пасажирів для персоналізованого досвіду). Схоже, ніхто з інвестиційних банкірів не потурбувався провести належну перевірку й зʼясувати, чому саме це екологічно, чи навіть який генеральний директор любить тренувати ворон у вільний час, бо інвестиційні гроші текли рікою.
За цю послугу також беруть плату залежно від пройденої відстані. Утім, оскільки ворони вміють літати, їм не потрібно триматися сітки доріг, і вони можуть летіти найкоротшим шляхом. Звісно, так було б не завжди, якби на шляху стояли величезні хмарочоси, але генеральний директор запускає цю послугу в Мангеттені, штат Канзас (він же «Маленьке яблуко»), де ворони легко перелітають невисокі будівлі. Питання про потенційний попит на таку послугу в Мангеттені, штат Канзас, і про те, як місцеві перехожі ставитимуться до всіх цих птахів, що літають над головою, залишимо на інший день.
Реалізуйте функцію as_crow_flies(start, end), яка приймає перехрестя start і end.
Поверніть відстань між ними по прямій.
as_crow_flies(0+0i, 3+4i)
#> 5
Генеральний директор навчив ворон орієнтуватися за напрямками, схожими на ті, що використовують водії. Однак генеральний директор обожнює Південну півкулю й навчав ворон за іншим компасом, ніж той, яким користується керівник проєкту для решти системи. Генеральний директор виявляється досить ексцентричною людиною. У компасі генерального директора північ відповідає відʼємному уявному напрямку, а південь - додатному уявному напрямку. Це протилежно до напрямку північ/південь у водіїв, тоді як схід/захід залишаються такими самими.
Реалізуйте функцію crows_directions(start, end), яка приймає перехрестя start і end.
Поверніть комплексне число, аналогічне до напрямку руху водія, але з північчю та півднем, поміняними місцями.
driver_directions(0+0i, 7+5i)
#> 7-5i
driver_directions(-2+3i, 4-5i)
#> 6+8i
Зареєструйтеся на Exercism, щоб вивчати й опановувати R, а також 21 концепція111 вправ та справжнє наставництво від людей, і все це безкоштовно.