Математичні операції в Kotlin
Що ж, ми розглянули ґрунт, на якому вже може будуватися програма.
Раніше ми вже розглядали одну з вбудованих функцій — println
. Ця функція друкувала в наш термінал (консоль) текст, який ми їй задавали.
Розгляньмо й інші.
Перейдемо до завдання: нам потрібно написати програму, що буде перемножувати введені користувачем цифри. Досить просто.
Для того, щоб отримати дані вводу від користувача, нам
знадобиться функція readln(): String
, що читає введення користувача з консолі.
Вона вбудована в мову, та як вже можна було помітити, повертає рядок.
Тобто, у нас буде щось на кшталт:
fun main() {
val number1: Int = readln()
val number2: Int = readln()
println(number1 * number2)
}
Ось і вся програма! Але, спробувавши її запустити, ми отримаємо помилку:
Type mismatch: inferred type is String but Int was expected
Переклавши на українську мову ми отримаємо наступне:
Невідповідність типів: передбачуваний тип - String, але очікувався Int.
Що це означає? Це означає, що нашим змінним number1
та number2
типу Int
(цілі числа)
задається невідповідний тип String
(рядок, aka звичайний текст).
На жаль, оскільки введення користувача може бути будь-яким: від цифр, до літер та будь-яких інших символів,
функція readln()
повертає тип String
(рядок, що може містити не тільки цифри).
Щоб це виправити, ми повинні перетворити рядок на ціле число (ну правда, бажано, перед цим перевірити введення користувача).
У Kotlin є функція toInt()
для рядків (aka тексту), що дуже полегшує нам життя. Вона конвертує рядок у цифру.
fun main() {
val number1: Int = readln().toInt()
val number2: Int = readln().toInt()
println(number1 * number2)
}
Подібні функції також існують і для інших типів-чисел:
String.toDouble()
String.toShort()
String.toFloat()
String.toLong()
Також подібні функції існують і між числами. Наприклад, ціле число може перетворюватися на число з плаваючою точкою (aka з комою, типу Double
).
Для чого це потрібно? Ну, наприклад, вам потрібно скласти одне ціле число й одне число з плаваючою точкою.
Оскільки Kotlin - це строго-типізована мова, просто так скласти цифри різних типів не вийде. Залежно від того, що вам потрібно, ви можете привести число з плаваючою точкою в ціле і навпаки.
val x = readln().toInt()
val y = readln().toDouble()
val double: Double = x.toDouble() + y
println(double)
val integer: Int = x + y.toInt()
println(integer)
Взагалі, якщо ви спробуєте скласти x+y
без перетворень, Kotlin автоматично виводитиме тип Double
. Але, під капотом, робиться те, що ми щойно розглянули. Але подібне працює лише з числами.
val x = readln().toInt()
val y = readln().toDouble()
val result: Double = x + y
println(result)
До речі, функція println
також виводить рядок у консоль. А ми їй віддаємо число. Чому для неї таких обмежень немає?
Все просто: функція println
приймає тип Any
(тобто будь-який тип даних) і неявно викликає на цьому типі toString()
(така ж вбудована функція в мову, що застосовується на будь-який створений об'єкт),
що повертає рядок з нашою цифрою.
Усередині там щось подібне:
fun println(value: Any) {
val string: String = value.toString()
// ...
}
Які ще цікаві функції існують? Давайте, вирішимо наступне завдання, заодно згадавши про умовні оператори:
І тут ми бачимо степінь! Що ж, знаючи, що таке степінь, неважко вирішити це завдання.
Я віддаю перевагу для більш ніж двох гілок з умовами, використовувати when
.
fun f(x: Double) {
return when {
x < 0 -> 3 * x
x >= 1 && x <= 100 -> x * x * x * x * x
else -> ? // що тут?
}
}
Якщо зі степенем ми розібрались, то що нам робити з коренем?
Для того, щоб отримати корінь від якогось числа, ми можемо скористуватись функцією sqrt(x: Double)
.
В результаті ми матимемо наступне:
import kotlin.math.sqrt
fun f(x: Double) {
return when {
x < 0 -> 3 * x
x >= 1 && x <= 100 -> x * x * x * x * x
else -> sqrt(x)
}
}
І наше завдання вирішено! Але якщо ми говоримо про вбудовані функції, то напевно є також якесь спрощення для степеня? Особливо, якщо думати про те, що було б, якщо степінь була б більшою. Так, спрощення є.
Для того, щоб підвести число до степеня, ми можемо скориставшись функцією Int.pow(times: Int)
.
Можна зробити наступним чином:
import kotlin.math.sqrt
import kotlin.math.pow
fun f(x: Double) {
return when {
x < 0 -> 3 * x
x >= 1 && x <= 100 -> x.pow(5)
else -> sqrt(x)
}
}
Дуже зручно! Особливо якщо у нас довільний степінь. Давайте ж виведемо результат у консоль:
fun main() {
val input: Double = readln().toDouble()
val output: String = f(input).toString()
println(output)
}
Виконайте наступний вираз мовою Kotlin:
З нового, ми тут бачимо модуль (або абсолютне число). Якщо ви не знайомі з поняттям абсолютного числа або модуля, то не хвилюйтесь. Все що вам потрібно знати – це те, що умовне завжди повертає позитивне (не мінусове) число.
Цю задачу можна вирішити декількома способами. Один із варіантів слідує з базового правила математики: мінус на мінус, завжди дає плюс.
Тобто маючи негативне число, все що нам потрібно, це додати до нього ще один мінус:
val negativeNumber = -1
val positiveNumber = -negativeNumber // ця змінна вже має позитивне значення.
За допомогою цього правила, можна перевернути число, але не забудьте перевірити чи число взагалі мінусове (негативне).
Тобто, можна зробити наступне:
fun absoluteNumber(x: Int): Int {
return if(x < 0) // перевіряємо чи число взагалі мінусове
-x // число мінусове, перевертаємо
else x // число позитивне, залишаємо як є
}
Ось ми й зробили аналог функції abs(x: Double)
з вбудованої бібліотеки математичних функцій
Kotlin. Ми можемо використати те, що ми написали, але візьмім готовий варіант.
Тож, користуючись знаннями про when
та функції pow
, sqrt
, abs
виконаємо задачу:
import kotlin.math.sqrt
import kotlin.math.pow
import kotlin.math.abs
fun f(x: Double): Double {
return when {
x >= 1 <= 20 -> 3 * x.pow(10)
x > 20 <= 100 -> sqrt(x)
else -> abs(x.pow(3))
}
}
І так нескладно ми вирішили це завдання.
І з інших цікавих функцій, хотілось би зазначити наступні:
max(x: Double, y: Double)
– повертає максимальне число споміж x та y.min(x: Double, y: Double)
– повертає максимальне число споміж x та y.
Подібних функцій досить багато, тому ми будемо їх розглядати під час проходження інших тем.