- Numbers
- Floating-point types
- Literal constants for numbers
- Numbers representation on the JVM
- Explicit number conversions
- Operations on numbers
- Division of integers
- Bitwise operations
- Floating-point numbers comparison
- Math.round vs Math.floor vs Math.ceil : Kotlin
- Math.round()
- Math.floor()
- Math.ceil()
- Common between Math.round, Math.floor and Math.ceil
- Difference between Math.round, Math.floor and Math.ceil
- Kotlin округление до десятых
- Functions
- abs
- acos
- acosh
- asin
- asinh
- atan
- atan2
- atanh
- cbrt
- ceil
- cos
- cosh
- exp
- expm1
- floor
- hypot
- IEEErem
- ln
- ln1p
- log
- log10
- log2
- max
- min
- nextDown
- nextTowards
Numbers
Kotlin provides a set of built-in types that represent numbers.
For integer numbers, there are four types with different sizes and, hence, value ranges:
9,223,372,036,854,775,807 (2 63 — 1)
When you initialize a variable with no explicit type specification, the compiler automatically infers the type with the smallest range enough to represent the value. If it is not exceeding the range of Int , the type is Int . If it exceeds, the type is Long . To specify the Long value explicitly, append the suffix L to the value. Explicit type specification triggers the compiler to check the value not to exceed the range of the specified type.
val one = 1 // Int val threeBillion = 3000000000 // Long val oneLong = 1L // Long val oneByte: Byte = 1
In addition to integer types, Kotlin also provides unsigned integer types. For more information, see Unsigned integer types.
Floating-point types
For real numbers, Kotlin provides floating-point types Float and Double that adhere to the IEEE 754 standard. Float reflects the IEEE 754 single precision, while Double reflects double precision.
These types differ in their size and provide storage for floating-point numbers with different precision:
You can initialize Double and Float variables with numbers having a fractional part. It’s separated from the integer part by a period ( . ) For variables initialized with fractional numbers, the compiler infers the Double type:
To explicitly specify the Float type for a value, add the suffix f or F . If such a value contains more than 6-7 decimal digits, it will be rounded:
Unlike some other languages, there are no implicit widening conversions for numbers in Kotlin. For example, a function with a Double parameter can be called only on Double values, but not Float , Int , or other numeric values:
fun main() < fun printDouble(d: Double) < print(d) >val i = 1 val d = 1.0 val f = 1.0f printDouble(d) // printDouble(i) // Error: Type mismatch // printDouble(f) // Error: Type mismatch >
To convert numeric values to different types, use explicit conversions.
Literal constants for numbers
There are the following kinds of literal constants for integral values:
- Decimals: 123
- Longs are tagged by a capital L : 123L
- Hexadecimals: 0x0F
- Binaries: 0b00001011
Octal literals are not supported in Kotlin.
Kotlin also supports a conventional notation for floating-point numbers:
You can use underscores to make number constants more readable:
val oneMillion = 1_000_000 val creditCardNumber = 1234_5678_9012_3456L val socialSecurityNumber = 999_99_9999L val hexBytes = 0xFF_EC_DE_5E val bytes = 0b11010010_01101001_10010100_10010010
There are also special tags for unsigned integer literals.
Read more about literals for unsigned integer types.
Numbers representation on the JVM
On the JVM platform, numbers are stored as primitive types: int , double , and so on. Exceptions are cases when you create a nullable number reference such as Int? or use generics. In these cases numbers are boxed in Java classes Integer , Double , and so on.
Nullable references to the same number can refer to different objects:
All nullable references to a are actually the same object because of the memory optimization that JVM applies to Integer s between -128 and 127 . It doesn’t apply to the b references, so they are different objects.
On the other hand, they are still equal:
Explicit number conversions
Due to different representations, smaller types are not subtypes of bigger ones. If they were, we would have troubles of the following sort:
// Hypothetical code, does not actually compile: val a: Int? = 1 // A boxed Int (java.lang.Integer) val b: Long? = a // Implicit conversion yields a boxed Long (java.lang.Long) print(b == a) // Surprise! This prints «false» as Long’s equals() checks whether the other is Long as well
So equality would have been lost silently, not to mention identity.
As a consequence, smaller types are NOT implicitly converted to bigger types. This means that assigning a value of type Byte to an Int variable requires an explicit conversion:
All number types support conversions to other types:
- toByte(): Byte
- toShort(): Short
- toInt(): Int
- toLong(): Long
- toFloat(): Float
- toDouble(): Double
In many cases, there is no need for explicit conversions because the type is inferred from the context, and arithmetical operations are overloaded for appropriate conversions, for example:
Operations on numbers
Kotlin supports the standard set of arithmetical operations over numbers: + , — , * , / , % . They are declared as members of appropriate classes:
You can also override these operators for custom classes. See Operator overloading for details.
Division of integers
Division between integers numbers always returns an integer number. Any fractional part is discarded.
This is true for a division between any two integer types:
To return a floating-point type, explicitly convert one of the arguments to a floating-point type:
Bitwise operations
Kotlin provides a set of bitwise operations on integer numbers. They operate on the binary level directly with bits of the numbers’ representation. Bitwise operations are represented by functions that can be called in infix form. They can be applied only to Int and Long :
Here is the complete list of bitwise operations:
- shl(bits) – signed shift left
- shr(bits) – signed shift right
- ushr(bits) – unsigned shift right
- and(bits) – bitwise AND
- or(bits) – bitwise OR
- xor(bits) – bitwise XOR
- inv() – bitwise inversion
Floating-point numbers comparison
The operations on floating-point numbers discussed in this section are:
- Equality checks: a == b and a != b
- Comparison operators: a < b , a >b , a = b
- Range instantiation and range checks: a..b , x in a..b , x !in a..b
When the operands a and b are statically known to be Float or Double or their nullable counterparts (the type is declared or inferred or is a result of a smart cast), the operations on the numbers and the range that they form follow the IEEE 754 Standard for Floating-Point Arithmetic.
However, to support generic use cases and provide total ordering, the behavior is different for operands that are not statically typed as floating-point numbers. For example, Any , Comparable <. >, or Collection types. In this case, the operations use the equals and compareTo implementations for Float and Double . As a result:
- NaN is considered equal to itself
- NaN is considered greater than any other element including POSITIVE_INFINITY
- -0.0 is considered less than 0.0
Here is an example that shows the difference in behavior between operands statically typed as floating-point numbers ( Double.NaN ) and operands not statically typed as floating-point numbers ( listOf(T) ).
Math.round vs Math.floor vs Math.ceil : Kotlin
Rounding up to the nearest Integer value functionality is something required a lot of times. Kotlin has a few inbuilt functions which can do the rounding up for us but they are a bit confusing. To decide when to use what, we need to understand which rounding function rounds up in which direction and which data types it can round up. Let’s understand them in detail before comparing. Before reading this blog, keep in mind that -3 is bigger than -4 and -3.5 is bigger than -3.51
Math.round()
- Math.round rounds up to the nearest Integer which can be above or below or even equal to the actual value.
- In the case of a positive number, anything which is equal to or below x.49 will be converted to a lower number ie x.00 whereas anything which is equal to or more than x.5 will be converted to a higher number ie x+1.00
- In the case of a negative number, anything which is equal to or below -x.51 will be converted to a lower number ie -x-1.00 whereas anything which is equal to or more than -x.5 will be converted to a higher number ie -x.00
println(Math.round(3.00))
//this will print: 3
println(Math.round(3.49))
//this will print: 3
println(Math.round(3.5))
//this will print: 4
println(Math.round(-3.00))
//this will print: -3
println(Math.round(-3.5))
//this will print: -3
println(Math.round(-3.51))
//this will print: -4
Math.floor()
- Math.floor rounds up to the nearest Integer which can be equal to or below the actual value.
- In the case of a positive number, anything between x.01 to x.99 will be converted to a lower number ie x.00 whereas x.00 will remain the same x.00
- In the case of a negative number, anything between -x.01 to -x.99 will be converted to a lower number ie -x-1.00 whereas -x.00 will remain the same -x.00
println(Math.floor(3.00))
//this will print: 3
println(Math.floor(3.01))
//this will print: 3
println(Math.floor(3.99))
//this will print: 3
println(Math.floor(-3.00))
//this will print: -3
println(Math.floor(-3.01))
//this will print: -4
println(Math.floor(-3.99))
//this will print: -4
Math.ceil()
- Math.ceil rounds up to the nearest Integer which can be equal to or above the actual value.
- In the case of a positive number, anything between x.01 to x.99 will be converted to an upper number ie x+1.00 whereas x.00 will remain the same x.00
- In the case of a negative number, anything between -x.01 to -x.99 will be converted to an upper number ie -x.00 whereas -x.00 will remain the same -x.00
println(Math.ceil(3.00))
//this will print: 3
println(Math.ceil(3.01))
//this will print: 4
println(Math.ceil(3.99))
//this will print: 4
println(Math.ceil(-3.00))
//this will print: -3
println(Math.ceil(-3.01))
//this will print: -3
println(Math.ceil(-3.99))
//this will print: -3
Common between Math.round, Math.floor and Math.ceil
- All three work on both Double as well as on Float .
- Although they round to the nearest Integer , the output still remains Double in the case of Double and Float in the case of Float .
Difference between Math.round, Math.floor and Math.ceil
- Math.round rounds up to the nearest Integer which can be above, below or equal to the actual value.
- x.0 to x.49 -> x.0
- x.5 to x.99 -> x+1.0
- -x to -x.5 -> x.0
- -x.51 to -x.99 -> -x-1.0
- x.0 to x.99 -> x.0
- -x.01 to -x.99 -> -x-1.0
- x.01 to x.99 -> x+1.0
- -x.01 to -x.99 -> -x.0
Kotlin округление до десятых
Returns the ulp (unit in the last place) of this value.
Returns the ulp of this value.
Functions
abs
Returns the absolute value of the given value x.
Returns the absolute value of the given value n.
acos
Computes the arc cosine of the value x; the returned value is an angle in the range from 0.0 to PI radians.
acosh
Computes the inverse hyperbolic cosine of the value x.
asin
Computes the arc sine of the value x; the returned value is an angle in the range from -PI/2 to PI/2 radians.
asinh
Computes the inverse hyperbolic sine of the value x.
atan
Computes the arc tangent of the value x; the returned value is an angle in the range from -PI/2 to PI/2 radians.
atan2
Returns the angle theta of the polar coordinates (r, theta) that correspond to the rectangular coordinates (x, y) by computing the arc tangent of the value y / x; the returned value is an angle in the range from -PI to PI radians.
atanh
Computes the inverse hyperbolic tangent of the value x.
cbrt
Returns the cube root of x. For any x , cbrt(-x) == -cbrt(x) ; that is, the cube root of a negative value is the negative of the cube root of that value’s magnitude. Special cases:
ceil
Rounds the given value x to an integer towards positive infinity.
cos
Computes the cosine of the angle x given in radians.
cosh
Computes the hyperbolic cosine of the value x.
exp
Computes Euler’s number e raised to the power of the value x.
expm1
floor
Rounds the given value x to an integer towards negative infinity.
hypot
Computes sqrt(x^2 + y^2) without intermediate overflow or underflow.
IEEErem
Computes the remainder of division of this value by the divisor value according to the IEEE 754 standard.
ln
Computes the natural logarithm (base E ) of the value x.
ln1p
log
Computes the logarithm of the value x to the given base.
log10
Computes the common logarithm (base 10) of the value x.
log2
Computes the binary logarithm (base 2) of the value x.
max
Returns the greater of two values.
min
Returns the smaller of two values.
nextDown
Returns the Double value nearest to this value in direction of negative infinity.
Returns the Float value nearest to this value in direction of negative infinity.
nextTowards
Returns the Double value nearest to this value in direction from this value towards the value to.
Returns the Float value nearest to this value in direction from this value towards the value to.