What are the rules and edge cases for digit underscores and radix prefixes in Kotlin numeric literals? Which forms are illegal and why?
answer
- underscores = cosmetic, between digits only
- no leading/trailing underscore
- not adjacent to prefix/suffix/point
- 0x hex, 0b binary, no octal
- prefix + digits + suffix order
basics
~20 sUnderscores are just visual separators between digits and don't change the value. They can't be at the start, the end, or right next to the 0x/0b prefix. Hex is 0x, binary is 0b, and there is no octal.
solid answer
~40 sUnderscores (`_`) in numeric literals are pure readability aids — the compiler strips them, so `1_000_000` equals `1000000`. The rules: an underscore must sit **between two digits**. It cannot lead (`_100`), trail (`100_`), appear adjacent to the radix prefix (`0x_FF`, `0_xFF`), or border the decimal point/exponent/`L`/`f` markers (`1_.0`, `100_L`). These illegal placements are compile errors. Radix prefixes are `0x`/`0X` for hexadecimal and `0b`/`0B` for binary; decimal needs no prefix; **there is no octal**, so a leading zero like `0123` is just decimal `123` with a redundant zero (and Kotlin disallows leading zeros that look octal in some forms). Underscores combine freely with valid prefixes and suffixes: `0xFF_EC_DE_5E`, `0b1010_0101`, `1_000L` are all valid.
code
kotlin · 6 linesval ok1 = 1_000_000
val ok2 = 0xCAFE_F00DL
val ok3 = 0b1010_0101
// val bad1 = 1000_ // trailing underscore: error
// val bad2 = 0x_FF // underscore after prefix: error
// val bad3 = _100 // leading underscore: errorgo deeper
Knows underscores are for readability and that 0x/0b are the prefixes.
States the between-digits-only placement rules and that there is no octal.
Explains why edge-position underscores are forbidden (tokenization) and composes prefix+underscore+suffix correctly.
Connects literal hygiene to code-review standards and lexer/grammar design rationale.
## Underscores are cosmetic Kotlin lets you group digits with `_` for legibility. The compiler removes them; they never affect the value or the type. ```kotlin val m = 1_000_000 // == 1000000 val card = 1234_5678_9012_3456L val hex = 0xFF_EC_DE_5E val bin = 0b1101_0010_0110_1001 ``` ## Placement rules (must be between digits) An underscore is legal **only between two digits**. Illegal placements are compile errors: - Leading: `_1000` - Trailing: `1000_` - Next to the radix prefix: `0_x12`, `0x_12` - Next to the suffix: `1000_L`, `1.0_f` - Next to the decimal point or exponent: `3_.14`, `1_e3`, `1e_3` Valid examples keep the underscore strictly inside the digit run: `0xFF_00`, `1_000.000_1`, `1_000L`. ## Radix prefixes - **Hexadecimal:** `0x` / `0X`, digits `0-9 a-f A-F`. Example: `0xCAFE`. - **Binary:** `0b` / `0B`, digits `0`/`1`. Example: `0b1010`. - **Decimal:** no prefix. - **Octal:** **not supported**. There is no `0o` form, and a C-style leading-zero octal is not a thing in Kotlin. A literal like `0123` is not interpreted as octal. ## Combining with suffixes Prefixes, underscores, and suffixes compose: `0xFFFF_FFFFL` is a hex `Long`, `0b1111_1111u` is an unsigned form (unsigned details belong to the Unsigned Types leaf). The ordering is always: prefix, digit groups (with internal underscores), then suffix. ## Why the restriction Forbidding edge-position underscores keeps tokenization unambiguous — the lexer can always tell where a number starts/ends and where a prefix/suffix attaches, avoiding parsing ambiguity with identifiers or operators.
- Does `0123` mean octal 83 in Kotlin?No. Kotlin has no octal literals; such a leading-zero form is not interpreted as octal (and Kotlin rejects integer literals with redundant leading zeros).
- Is `1_000_000` a different value from `1000000`?No. Underscores are stripped by the compiler; both are the same Int value.
Underscores are like the spaces in a phone number — they help you read it but dialing ignores them, and you can't put a space before the first digit.
saying these in an interview costs you the question
- Thinking underscores change the numeric value
- Allowing leading or trailing underscores
- Believing Kotlin supports octal via leading zero
- Placing underscores next to 0x/0b or L/f
- Claiming there is a 0o octal prefix