Julia - мова загального призначення, яку можна використовувати для більшості програмних завдань. Однак на практиці основні випадки використання зазвичай повʼязані з інженерією та наукою. В основі дизайну мови лежать швидкі, універсальні й витончені числові обчислення.
Ціле число - це «кругле» число без десяткової коми.
У концепті Основи ми бачили, що ціле значення можна присвоїти змінній, не вказуючи тип.
Для читабельності як розділювач розрядів можна використовувати символи підкреслення. Компілятор їх ігнорує.
julia> x = 3
3
julia> typeof(x)
Int64
julia> large_number = 1_234_567_890
1234567890
Не дивно, що числа з плаваючою комою мають десяткову кому та дробову частину після неї.
julia> f = 3.45
3.45
julia> typeof(f)
Float64
Звісно, підтримується наукова нотація.
julia> avogadro = 6.02e23
6.02e23
Максимальне й мінімальне значення можуть здивувати:
julia> typemax(Float64)
Inf
julia> typemin(Float64)
-Inf
Нескінченність - допустиме значення!
Як ми обговорювали в концепті Основи, арифметичні оператори здебільшого працюють так само, як звичайна арифметика, яку вивчають діти.
Звернімо увагу: піднесення до степеня використовує ^, а не ** (обидва поширені в інших мовах).
2 + 3 # 5 (addition)
2 - 3 # -1 (subtraction)
2 * 3 # 6 (multiplication)
8 / 2 # 4.0 (division)
8 % 3 # 2 (remainder)
2 ^ 3 # 8 (exponentiation)
Проте кілька деталей, специфічних для Julia, варті обговорення.
julia> x = 4.2
4.2
julia> 2 * x
8.4
julia> 2x
8.4
julia> 2.4x
10.08
Це може здивувати.
Завжди можна використати * як інфіксний оператор, як і в більшості інших мов програмування.
Однак Julia створювали люди, які вважають, що код має якомога більше нагадувати математичні рівняння.
Оскільки назви змінних мають починатися з літери, число (ціле або з плаваючою комою) перед назвою сприймається як неявне множення.
Наприклад, якщо нам потрібна площа поверхні сфери, замість 4 * pi * r * r ми могли б зробити так:
julia> surface(r) = 4π * r^2
surface (generic function with 1 method)
julia> surface(3)
113.09733552923255
Хоча π - вбудована константа, це також (грецька) літера.
Тому парсеру все одно потрібен один явний *, щоб відокремити π від r.
Використання / як інфіксного оператора завжди дає результат з плаваючою комою, навіть для цілих вхідних даних.
Для цілочисельного ділення є більше варіантів.
julia> 10 / 3 # floating-point division
3.3333333333333335
julia> div(10, 3) # integer division
3
julia> 10 ÷ 3 # synonym for div()
3
julia> 10 // 3 # rational number (fraction)
10//3
Функція div() призначена для цілочисельного ділення, і результат відкидається в напрямку нуля: вниз для додатних чисел, вгору для відʼємних.
Як синонім можна використати інфіксний оператор ÷, знову ж таки прагнучи зробити запис математичнішим.
Якщо ми користуємося редактором, який розуміє Julia, введімо \div, а потім натиснімо клавішу <Tab>.
Оператор // виходить за межі цього концепту.
Поки що скажімо лише, що результат // - це «раціональне» число, яке більшість людей називає дробом.
Часто це відбувається автоматично:
julia> x = 2 + 3.5
5.5
julia> typeof(x)
Float64
Ми додали Int64 до Float64 й отримали результат Float64.
Насправді ціле число непомітно перетворилося на Float64 ще до самого додавання.
Перетворення з плаваючою комою на ціле число неминуче складніші. Що робити з тим, що стоїть після десяткової коми?
round() перетворює число на найближче ціле, а за рівної відстані, як-от 4.5, округлює до найближчого парного цілого.floor() округлює вниз, ceil() округлює вгору, trunc() округлює в напрямку нуля.Int32(), завершиться помилкою InexactError.Однак типово ці функції повертають не той цілий тип, який міг бути потрібен. Бажаний тип вихідних даних можна вказати.
julia> round(4.5)
4.0
julia> ceil(Int, 4.3)
5
Округлення до заданої кількості цифр після десяткової коми також можливе за допомогою ключового слова digits.
julia> round(π, digits=10)
3.1415926536
Невже тут просто виникає помилка? Насправді все не так просто.
Цілочисельне ділення з ÷ або // спричинить помилку, як і можна очікувати.
Ділення з плаваючою комою за допомогою / дотримується радше інженерного підходу, ніж стандартного підходу інформатики:
julia> 2 / 0
Inf
julia> 0 / 0
NaN
Як ми обговорювали в попередньому розділі, нескінченність - це допустиме число з плаваючою комою в Julia, яке позначається Inf.
Коли чисельник також дорівнює нулю, результат математично не визначений.
Тоді Julia трактує його як «не число», позначене NaN.
Наш друг Чендлер планує відвідати екзотичні країни по всьому світу. На жаль, Чендлер не дуже добре знає математику. Він дуже хвилюється, що під час подорожі його обдурять на обміні валют, і хоче, щоб ми зробили для нього калькулятор валют. Ось його вимоги до застосунку:
Створіть функцію exchange_money(), яка приймає 2 параметри:
budget: сума грошей, яку ми плануємо обміняти.exchange_rate: сума національної валюти, що дорівнює одній одиниці іноземної валюти.Ця функція має повертати значення обміняної валюти.
Примітка: Якщо наша валюта - це USD і ми хочемо обміняти USD на EUR за обмінного курсу 1.20, то 1.20 USD == 1 EUR.
julia> exchange_money(127.5, 1.2)
106.25
Створіть функцію get_change(), яка приймає 2 параметри:
budget: сума грошей до обміну.exchanging_value: сума грошей, яку беруть з бюджету для обміну.Ця функція має повертати суму грошей, що залишається від бюджету.
julia> get_change(127.5, 120)
7.5
Створіть функцію get_value_of_bills(), яка приймає 2 параметри:
denomination: вартість однієї банкноти.number_of_bills: загальна кількість банкнот.Цей обмінний пункт працює лише з готівкою певних номіналів. Загальна сума, яку ми отримуємо, має ділитися на вартість однієї «банкноти», або одиниці, тож може залишитися дріб чи остача. Функція має повертати лише загальну вартість банкнот (без дробових сум), які видасть обмінний пункт. На жаль, остача/решта дістається обмінному пункту як додатковий бонус.
julia> get_value_of_bills(5, 128)
640
Створіть функцію get_number_of_bills(), яка приймає amount і denomination.
Ця функція має повертати кількість банкнот, які можна отримати в межах заданого amount. Інакше кажучи: скільки цілих банкнот вміщується в початкову суму? Памʼятайте: отримати можна лише цілі банкноти, а не частини банкнот, тож діліть відповідно. По суті, ми округлюємо вниз до найближчої цілої банкноти, тобто номіналу.
julia> get_number_of_bills(127.5, 5)
25
Створіть функцію get_leftover_of_bills(), яка приймає amount і denomination.
Ця функція має повертати суму залишку, яку неможливо повернути з початкової суми amount за заданого номіналу банкнот. Дуже важливо точно знати, скільки залишає собі обмінний пункт.
julia> get_leftover_of_bills(127.5, 20)
7.5
Створіть функцію exchangeable_value(), яка приймає budget, exchange_rate, spread і denomination.
Параметр spread - це відсоток, який стягують як комісію за обмін, записаний цілим числом.
Його потрібно перевести в десяткове число, поділивши на 100.
Якщо 1.00 EUR == 1.20 USD, а spread дорівнює 10, то загальний обмінний курс насправді становитиме 1.00 EUR == 1.32 USD, бо 10% від 1.20 становить 0.12, і ця додаткова комісія додається до курсу обміну.
Ця функція має повертати максимальне значення нової валюти з урахуванням обмінного курсу та spread. Памʼятайте, що номінал валюти - це ціле число, і його не можна поділити на частини.
Примітка: Повернене значення має бути цілим числом.
julia> exchangeable_value(127.25, 1.20, 10, 20)
80
julia> exchangeable_value(127.25, 1.20, 10, 5)
95
Зареєструйтеся на Exercism, щоб вивчати й опановувати Julia, а також 35 концепцій128 вправ та справжнє наставництво від людей, і все це безкоштовно.