skip to content

Beyond nextInt, what other primitive random values can kotlin.random.Random produce, and what are the bound semantics for nextDouble?

level: middleimportance: nice to knowfreq 40%

answer

  1. nextDouble() is [0.0, 1.0)
  2. from inclusive, until exclusive everywhere
  3. nextFloat has no bounded overload
  4. nextBytes fills a ByteArray
  5. nextLong/nextBoolean/nextBits also exist

basics

~10 s

Random can produce Long, Double, Float, Boolean, Int, and random bytes. nextDouble() returns a value from 0.0 up to (but not including) 1.0; overloads let you set bounds.

solid answer

~30 s

`kotlin.random.Random` exposes `nextInt`, `nextLong`, `nextDouble`, `nextFloat`, `nextBoolean`, `nextBits(bitCount)`, and `nextBytes(...)`. `nextDouble()` returns a uniform `Double` in `[0.0, 1.0)` — zero inclusive, one exclusive. `nextDouble(until)` gives `[0.0, until)` and `nextDouble(from, until)` gives `[from, until)`. `nextFloat()` mirrors this for `[0.0f, 1.0f)` but has no bounded overloads. `nextBoolean()` returns true/false with ~50% probability. `nextBytes(size)` fills a fresh `ByteArray`, and overloads can fill an existing array or a sub-range — handy for generating random binary data. Like the int variants, invalid ranges (e.g. from >= until) throw `IllegalArgumentException`. All of these respect the generator instance, so seeding applies uniformly.

code

kotlin · 4 lines
kotlin
import kotlin.random.Random

fun randomFloatInRange(from: Float, until: Float): Float =
    from + Random.nextFloat() * (until - from) // scale manually, no Float overload

go deeper

for a junior

Knows nextDouble() returns a fractional value between 0 and 1.

for a middle

Knows the [0.0,1.0) bound, the bounded overloads, and that nextFloat lacks bounded variants.

for a senior

Knows the full surface (nextLong/nextBytes/nextBits) and scales floats manually; aware of the security boundary.

for a principal

Reasons about distribution/precision trade-offs and steers teams to CSPRNGs when bytes back identifiers or secrets.

## The full primitive surface of `Random` `kotlin.random.Random` is not just `nextInt`. It produces every primitive numeric type plus booleans and raw bytes. ### Doubles and floats - `nextDouble(): Double` — uniform in **`[0.0, 1.0)`** (0.0 possible, 1.0 never). - `nextDouble(until: Double): Double` — `[0.0, until)`. - `nextDouble(from: Double, until: Double): Double` — `[from, until)`. - `nextFloat(): Float` — `[0.0f, 1.0f)`. **No bounded overloads** for Float; scale manually if you need a range. The half-open `[from, until)` convention matches `nextInt`: lower inclusive, upper exclusive. ```kotlin import kotlin.random.Random val probability = Random.nextDouble() // [0.0, 1.0) val temp = Random.nextDouble(-10.0, 40.0) // [-10.0, 40.0) val coin = Random.nextBoolean() // true or false val bigId = Random.nextLong(1_000_000) // [0, 1_000_000) ``` ### Longs and booleans - `nextLong()`, `nextLong(until)`, `nextLong(from, until)` — same semantics as Int, for 64-bit values. - `nextBoolean()` — ~50/50 true/false. ### Bits and bytes - `nextBits(bitCount: Int): Int` — an Int holding `bitCount` random bits (0..32). Lower-level building block. - `nextBytes(size: Int): ByteArray` — a new array of `size` random bytes. - `nextBytes(array: ByteArray)` and `nextBytes(array, fromIndex, toIndex)` — fill an existing array (or sub-range) in place. ```kotlin val payload = Random.nextBytes(16) // 16 random bytes (NOT for crypto) ``` ### Errors and uniformity Invalid bounds (`from >= until`, negative `until`) throw `IllegalArgumentException`. Distributions are uniform across the requested interval. Floating-point ranges can lose precision for extreme magnitudes, but for typical ranges the distribution is uniform. ### Reminder None of these are secure. `nextBytes` is convenient for test fixtures or non-security identifiers, but secrets need a CSPRNG (`SecureRandom`).

  • Can nextDouble() ever return exactly 1.0?
    No. The interval is half-open [0.0, 1.0); 0.0 is possible but 1.0 is excluded.
  • How do you get a random Float in a custom range given there is no bounded nextFloat?
    Scale manually: from + nextFloat() * (until - from), accepting the half-open semantics.

saying these in an interview costs you the question

  • Claiming nextDouble() can return 1.0
  • Assuming nextFloat(from, until) exists
  • Forgetting nextBytes / nextBoolean / nextLong exist
  • Using nextBytes for cryptographic secrets

context