Zahlentypen
Verschiedene Zahlentypen werden auf unterschiedliche Weise gespeichert.
Wenn Sie einen Bezeichner erstellen und ihm einen Ganzzahlwert zuweisen, leitet Kotlin den Int-Typ ab:
// NumberTypes/InferInt.kt
fun main() {
val million = 1_000_000 // Infers Int
println(million)
}
/* Output:
1000000
*/
Für die Lesbarkeit erlaubt Kotlin Unterstriche innerhalb numerischer Werte.
Die grundlegenden mathematischen Operatoren für Zahlen sind diejenigen, die in den meisten Programmiersprachen verfügbar sind: Addition (+), Subtraktion (-), Division (/), Multiplikation (*) und Modulus (%), was den Rest aus der Ganzzahldivision ergibt:
// NumberTypes/Modulus.kt
fun main() {
val numerator: Int = 19
val denominator: Int = 10
println(numerator % denominator)
}
/* Output:
9
*/
Ganzzahl-Division schneidet das Ergebnis ab:
// NumberTypes/IntDivisionTruncates.kt
fun main() {
val numerator: Int = 19
val denominator: Int = 10
println(numerator / denominator)
}
/* Output:
1
*/
Wenn die Operation das Ergebnis gerundet hätte, wäre die Ausgabe 2.
Die Reihenfolge der Operationen folgt der grundlegenden Arithmetik:
// NumberTypes/OpOrder.kt
fun main() {
println(45 + 5 * 6)
}
/* Output:
75
*/
Die Multiplikation 5 * 6 wird zuerst ausgeführt, gefolgt von der
Addition 45 + 30.
Wenn Sie möchten, dass 45 + 5 zuerst erfolgt, verwenden Sie Klammern:
// NumberTypes/OpOrderParens.kt
fun main() {
println((45 + 5) * 6)
}
/* Output:
300
*/
Nun berechnen wir den Body-Mass-Index (BMI), der das Gewicht in Kilogramm
dividiert durch das Quadrat der Größe in Metern ist. Wenn Sie einen BMI von weniger als
18,5 haben, sind Sie untergewichtig. Zwischen 18,5 und 24,9 ist Normalgewicht. Ein BMI von
25 und höher ist Übergewicht. Dieses Beispiel zeigt auch den bevorzugten Formatierungsstil,
wenn Sie die Parameter der Funktion nicht in eine einzige Zeile passen können:
// NumberTypes/BMIMetric.kt
fun bmiMetric(
weight: Double,
height: Double
): String {
val bmi = weight / (height * height) // [1]
return if (bmi < 18.5) "Underweight"
else if (bmi < 25) "Normal weight"
else "Overweight"
}
fun main() {
val weight = 72.57 // 160 lbs
val height = 1.727 // 68 inches
val status = bmiMetric(weight, height)
println(status)
}
/* Output:
Normal weight
*/
-
[1] Wenn Sie die Klammern entfernen, teilen Sie
weightdurchheightund multiplizieren dann dieses Ergebnis mitheight. Das ergibt eine viel größere Zahl und ist die falsche Antwort.
bmiMetric() verwendet Doubles für das Gewicht und die Größe. Ein Double kann sehr große und sehr kleine Gleitkommazahlen aufnehmen.
Hier ist eine Version, die englische Einheiten verwendet, dargestellt durch Int-Parameter:
// NumberTypes/BMIEnglish.kt
fun bmiEnglish(
weight: Int,
height: Int
): String {
val bmi =
weight / (height * height) * 703.07 // [1]
return if (bmi < 18.5) "Underweight"
else if (bmi < 25) "Normal weight"
else "Overweight"
}
fun main() {
val weight = 160
val height = 68
val status = bmiEnglish(weight, height)
println(status)
}
/* Output:
Underweight
*/
Warum unterscheidet sich das Ergebnis von bmiMetric(), das Doubles verwendet? Wenn Sie eine Ganzzahl durch eine andere Ganzzahl teilen, erzeugt Kotlin ein Ganzzahlergebnis. Die Standardmethode, um mit dem Rest während der ganzzahligen Division umzugehen, ist das Abschneiden, was bedeutet, “abschneiden und wegwerfen” (es gibt kein Runden). Wenn Sie also 5 durch 2 teilen, erhalten Sie 2, und 7/10 ist null. Wenn Kotlin bmi in Ausdruck [1] berechnet, teilt es 160 durch 68 * 68 und erhält null. Es multipliziert dann null mit 703.07, um null zu erhalten.
Um dieses Problem zu vermeiden, verschieben Sie 703.07 an den Anfang der Berechnung. Die Berechnungen werden dann gezwungen, Double zu sein:
val bmi = 703.07 * weight / (height * height)
Die Double Parameter in bmiMetric() verhindern dieses Problem. Rechnen Sie so früh wie möglich auf den gewünschten Typ um, um die Genauigkeit zu erhalten.
Alle Programmiersprachen haben Grenzen, was sie innerhalb einer Ganzzahl speichern können. Der Int Typ in Kotlin kann Werte zwischen -231 und +231-1 annehmen, eine Einschränkung der 32-Bit Darstellung von Int. Wenn Sie zwei Ints addieren oder multiplizieren, die groß genug sind, wird das Ergebnis überlaufen:
// NumberTypes/IntegerOverflow.kt
fun main() {
val i: Int = Int.MAX_VALUE
println(i + i)
}
/* Output:
-2
*/
Int.MAX_VALUE ist ein vordefinierter Wert, der die größte Zahl darstellt, die ein Int halten kann.
Der Überlauf erzeugt ein Ergebnis, das eindeutig falsch ist, da es sowohl negativ als auch viel kleiner ist, als wir erwarten. Kotlin gibt eine Warnung aus, wann immer es einen potenziellen Überlauf erkennt.
Es liegt in Ihrer Verantwortung als Entwickler, Überläufe zu verhindern. Kotlin kann nicht immer Überläufe während der Kompilierung erkennen, und es verhindert keine Überläufe, da dies eine untragbare Leistungseinbuße zur Folge hätte.
Wenn Ihr Programm große Zahlen enthält, können Sie Longs verwenden, die Werte von -263 bis +263-1 aufnehmen. Um ein val vom Typ Long zu definieren, können Sie den Typ explizit angeben oder ein L am Ende eines numerischen Literals hinzufügen, was Kotlin anweist, diesen Wert als Long zu behandeln:
// NumberTypes/LongConstants.kt
fun main() {
val i = 0 // Infers Int
val l1 = 0L // L creates Long
val l2: Long = 0 // Explicit type
println("$l1 $l2")
}
/* Output:
0 0
*/
Durch die Verwendung von Longs verhindern wir den Überlauf in IntegerOverflow.kt:
// NumberTypes/UsingLongs.kt
fun main() {
val i = Int.MAX_VALUE
println(0L + i + i) // [1]
println(1_000_000 * 1_000_000L) // [2]
}
/* Output:
4294967294
1000000000000
*/
Die Verwendung eines numerischen Literals in sowohl [1] als auch [2] erzwingt Long-Berechnungen und ergibt ebenfalls ein Ergebnis vom Typ Long. Der Ort, an dem das L erscheint, ist unwichtig. Wenn einer der Werte Long ist, ist der resultierende Ausdruck Long.
Obwohl sie viel größere Werte als Ints halten können, haben Longs immer noch Größenbeschränkungen:
// NumberTypes/BiggestLong.kt
fun main() {
println(Long.MAX_VALUE)
}
/* Output:
9223372036854775807
*/
Long.MAX_VALUE ist der größte Wert, den ein Long halten kann.
Übungen und Lösungen finden Sie unter www.AtomicKotlin.com.