На этом шаге мы рассмотрим особенности такого преобразования.
Настало время изъять деньги из кошелька игрока. В кошельке хранится целое число золотых и серебряных монет, но цена напитка выражена в золоте как Double.
Чтобы осуществить продажу, для начала переведем золото и серебро в одно значение, чтобы можно было вычесть цену. Добавьте переменную в performPurchase() для представления общего количества денег в кошельке. Одна золотая монета стоит 100 серебряных, поэтому разделите серебряные монеты игрока на 100 и добавьте результат к количеству золотых монет, чтобы получить общую сумму. Переменные totalPurse и price одного типа, Double, поэтому вычтите цену из суммы в кошельке и присвойте результат новой переменной.
. . . . . fun performPurchase() { displayBalance() val totalPurse = playerGold + (playerSilver / 100.0) println("Total purse: $totalPurse") println("Purchasing item for $price") val remainingBalance = totalPurse - price } . . . . .
Рис.1. Вычитание цены (Tavern.kt)
Для начала вычисляем общую сумму totalPurse и выводим ее. Обратите внимание, что делитель, используемый при переводе playerSilver для totalPurse, содержит дробную часть - 100.0, а не просто 100.
Если разделить playerSilver, значение типа Int, на число 100, которое тоже имеет тип Int, Kotlin вернет не 0.10 типа Double. Вместо этого вы получите другое значение Int - 0, потеряв такую важную дробную часть. (Попробуйте это в REPL.)
Поскольку оба числа являются целыми, Kotlin использует целочисленную арифметику, которая не позволяет получить в результате дробную часть.
Чтобы получить дробную часть, надо, чтобы Kotlin выполнил арифметические действия с плавающей точкой, для чего достаточно включить в операцию хотя бы один тип, поддерживающий дробные значения. Попробуйте еще раз выполнить вычисления в REPL, но в этот раз добавьте в одно из чисел дробную часть, чтобы подсказать, что должна использоваться арифметика с плавающей точкой, и в результате вы получите Double(0.1).
Преобразовав содержимое кошелька в totalPurse, вычтите цену Dragon's Breath:
val remainingBalance = totalPurse - price
Чтобы увидеть результат вычислений, введите 10.1-5.91 в REPL. Если вы не работали с числовыми типами на другом языке программирования, результат может вас удивить.
Ожидая увидеть результат 4.19, вы получите 4.1899999999999995. Так компьютер представляет себе дробные числа с плавающей точкой. Слово "плавающая" означает, что десятичная точка может располагаться в любом месте (она "плавает"). Числа с плавающей точкой в компьютере представляют лишь приближенное значение реального числа. Это обусловлено стремлением дать возможность представлять широкий диапазон чисел с разным числом разрядов и обеспечить высокую производительность.
Точность представления числа с дробной частью диктуется требованиями к вычислениям. Например, если бы вы программировали сервер центрального банка NyetHack, выполняющий огромное количество финансовых операций с дробными числами, вы предпочли бы выражать числа с большей точностью, даже если это приведет к потерям времени. Вообще, для финансовых расчетов предпочтительнее использовать тип BigDecimal, чтобы получить более высокую точность округления в вычислениях с плавающей точкой. (Это тот же тип BigDecimal, который может быть знаком вам по Java).
Однако для нашей виртуальной таверны вполне достаточно точности, которую дает тип в Double.
На следующем шаге мы рассмотрим форматирование значений типа Double.