
Make Numbers More Readable in Your Code
- February 28, 2025
- 8 min read
- Programming concepts , Software quality
Table of Contents
Have you ever seen a giant number in your code, like 100000000
, and thought, “What even is this?”
Is it 10 million? 100 million? Or just a random string of digits?
You start counting, one by one… just to figure it out.
But what if I told you there’s a simple trick that makes numbers in code much easier to read?
Many programming languages offer features to make numbers clearer, while some still don’t.
I went through 50 of the most popular programming languages to find out which ones help you write more readable numbers—and how you can use them in your own code.
​
The Power of Numeric Separators
In natural languages, we make numbers more readable by inserting numeric separators between digits.
Different regions format large numbers differently.
- In English, we use a comma as a separator (e.g.,
100,000,000
). - In Italy, they use a dot (e.g.,
100.000.000
). - Switzerland uses an apostrophe (e.g.,
100'000'000
). - France uses a single blank space (e.g.,
100 000 000
).
These all separate numbers every three digits from the right.
It would be nice to use a similar separator for numbers in your code, right?
​
Numeric Separators in Code
I checked 50 top programming languages and found this: Many modern languages support numeric separators! Even older languages have recently added the feature.
But not all languages support numeric separators.
Of the 50 languages I checked, 16 do not support them, while 34 do.
Here’s a breakdown of which languages support numeric separators, how they implement them, and when they were introduced.
No. | Language | Numeric Separators | Later Support Version |
---|---|---|---|
1 | Ada | ✅ Yes (e.g., 1_000_000 ) |
|
2 | ASM (nasm) | ✅ Yes (e.g., 1_000_000 ) |
nasm-2.03 (2009) |
3 | AWK | ❌ No | |
4 | Bash (Shell) | ❌ No | |
5 | C | ✅ Yes (e.g., 1'000'000 ) |
C23 (2024) |
6 | C# | ✅ Yes (e.g., 1_000_000 ) |
C# 7.0 (2017) |
7 | C++ | ✅ Yes (e.g., 1'000'000 ) |
C++14 (2014) |
8 | Clojure | ❌ No | |
9 | Common Lisp | ❌ No | |
10 | Crystal | ✅ Yes (e.g., 1_000_000 ) |
|
11 | Dart | ✅ Yes (e.g., 1_000_000 ) |
Dart 3.6 (2024) |
12 | D | ✅ Yes (e.g., 1_000_000 ) |
|
13 | Delphi/Objective Pascal | ❌ No | |
14 | Elixir | ✅ Yes (e.g., 1_000_000 ) |
|
15 | Elm | ❌ No | |
16 | Erlang | ✅ Yes (e.g., 1_000_000 ) |
Erlang/OTP 23.0 (2020) |
17 | F# | ✅ Yes (e.g., 1_000_000 ) |
F# 4.1 (2017) |
18 | Fortran | ❌ No | |
19 | Gleam | ✅ Yes (e.g., 1_000_000 ) |
|
20 | Go | ✅ Yes (e.g., 1_000_000 ) |
Go 1.13 (2019) |
21 | Groovy | ✅ Yes (e.g., 1_000_000 ) |
Groovy 2.0 (2012) |
22 | Haskell | ✅ Yes (e.g., 1_000_000 ) |
Haskell 8.6.1 (2018) |
23 | Java | ✅ Yes (e.g., 1_000_000 ) |
Java 7 (2011) |
24 | JavaScript | ✅ Yes (e.g., 1_000_000 ) |
ES2021 (2021) |
25 | Julia | ✅ Yes (e.g., 1_000_000 ) |
|
26 | Kotlin | ✅ Yes (e.g., 1_000_000 ) |
|
27 | Lua | ❌ No | |
28 | MATLAB | ❌ No | |
29 | Mojo | ✅ Yes (e.g., 1_000_000 ) |
|
30 | Nim | ✅ Yes (e.g., 1_000_000 ) |
|
31 | Objective-C | ❌ No | |
32 | OCaml | ✅ Yes (e.g., 1_000_000 ) |
|
33 | Perl | ✅ Yes (e.g., 1_000_000 ) |
|
34 | PHP | ✅ Yes (e.g., 1_000_000 ) |
PHP 7.4 (2019) |
35 | PowerShell | ❌ No | |
36 | Prolog | ❌ No | |
37 | Python | ✅ Yes (e.g., 1_000_000 ) |
Python 3.6 (2016) |
38 | R | ❌ No | |
39 | Racket | ❌ No | |
40 | Raku | ✅ Yes (e.g., 1_000_000 ) |
|
41 | Ruby | ✅ Yes (e.g., 1_000_000 ) |
|
42 | Rust | ✅ Yes (e.g., 1_000_000 ) |
|
43 | Scala | ✅ Yes (e.g., 1_000_000 ) |
Scala 2.13.0 (2019) |
44 | Solidity | ✅ Yes (e.g., 1_000_000 ) |
Solidity 0.4.22 (2018) |
45 | Swift | ✅ Yes (e.g., 1_000_000 ) |
|
46 | Tcl | ❌ No | |
47 | TypeScript | ✅ Yes (e.g., 1_000_000 ) |
|
48 | V | ✅ Yes (e.g., 1_000_000 ) |
|
49 | Visual Basic | ❌ No | |
50 | Zig | ✅ Yes (e.g., 1_000_000 ) |
It’s quite surprising that Fortran, Matlab, and R don’t (yet) support numeric separators, especially since they’re heavily used for scientific computations and data analysis.
On the flip side, it’s not surprising that Bash, PowerShell, and AWK don’t support them, as they’re primarily designed for command-line scripting, not complex calculations or software development.
Among the languages that support numeric separators, we have some of the most popular and widely used ones, like: C, C++, C#, Go, Java, JavaScript, Python, Rust, and mobile development languages like Kotlin and Swift.
Many of these languages added the feature in later versions. Even C, which dates back to the 80s, only introduced numeric separators in 2024 with the C23 version.
So, what do these languages use as numeric separators? Well, all except C and C++ use the underscore symbol (_
). C and C++ are the two outliers, using the tick or apostrophe symbol ('
) instead. Don’t ask me why!
Numeric separators work with different types of numbers, including:
- Floating-point numbers (e.g.,
3.141_592_653
) - Binary numbers (e.g.,
0b1111_0000_1010
) - Hexadecimal numbers (e.g.,
0xFF_AA_BB_CC
) - Octal numbers (e.g.,
0o777_123_456
)
The cool thing is, the separators don’t always have to be placed at thousands; you can use them to group digits in any format for better readability.
Newsletter
Subscribe to our newsletter and stay updated.
Some languages don’t allow consecutive or trailing separators.
For example, most languages, like C, C++, Go, JavaScript, and Python, allow only a single numeric separator between digits.
But some languages, like C#, Dart, Kotlin, Java, and Haskell, let you use consecutive separators. This can help when you’re working with really large numbers, making them easier to scan at a glance.
1var m = 1__000_000__000_000;
Others, like Rust, Swift, and Netwide Assembler, even allow trailing separators. Don’t ask me why, but hey, if you like making your code look quirky, why not?
1let m = 1__000_000__000_000__;
Use numeric separators to improve readability, but don’t go overboard. Stick to grouping by thousands to maintain clarity.
Avoid using strange formats like 1_50
or 1__000
, unless your code is specific to a region or context (for example, the Indian number system: 10_00_00_000
).
The goal is to make your numbers easier to understand at a glance, not harder. So, keep it simple!
​
Exponential Notation
What if your language doesn’t support numeric separators? Well, exponential notation can sometimes help.
Exponential notation is a way of writing large numbers by multiplying a base number (the mantissa) by 10 raised to an exponent.
For example, 100000000
is equal to 1 x 10^8
.
This format is supported by most programming languages, so it’s a great alternative when separators aren’t available.
Among the 50 languages I checked, only Bash doesn’t support exponential notation. For all the others, the notation is mantissa e exponent (e.g., p = 100000000
will be written as p = 1e8
).
But here’s the catch: If the number isn’t a clean power of ten, it can still be hard to read. For example, writing 5 billion and 1 in exponential form doesn’t make it much clearer (5000000001
vs 5.000000001e9
), since the mantissa can still be difficult to parse at a glance.
In languages that support numeric separators, you can combine the two—numeric separators and exponential notation—for maximum clarity!
Instead of 1.23456789e-8
, write 1.234_567_89e-8
to improve readability.
Note
Exponential notation only applies to floating-point numbers in most languages, but there are exceptions.
Here’s a list of languages where exponential notation also works on integers:
Ada, AWK, C, C++, Clojure, Common Lisp, Crystal, Fortran, Go, Groovy, Javascript, Matlab, Objective-C, Perl, PHP, Powershell, R, Raku, Solidity, Tcl, Typescript, Visual Basic.
​
Use Constant Folding for Cleaner Code
Now, there’s another trick that works in all 50 languages: constant folding.
Let’s say you need to specify a timeout duration in milliseconds for a function. You could write:
setTimeout(1800000);
But that’s a mess. Is that 18 minutes? 30 minutes? You’d have to stop and think.
Instead, break it down:
setTimeout(30 * 60 * 1000);
Now, it’s instantly clear that this represents 30 minutes.
Instead of writing a giant number directly in your code, break it down into meaningful expressions—especially when passing constants to function calls.
And thanks to constant folding, the compiler evaluates this at compile time, so there’s no performance cost. For interpreted languages, the cost is negligible due to runtime optimizations.
This is especially helpful when working with units we don’t use daily—things like milliseconds, bytes, or nanoseconds.
When working with a unit that isn’t intuitive, breaking it down into a meaningful expression makes your code much easier to understand at a glance.
Newsletter
Subscribe to our newsletter and stay updated.
​
Final Thoughts
So, what did we learn?
Numeric separators, exponential notation, and constant folding are all tools that make numbers more readable.
Many modern languages support numeric separators—so use them when you can!
If your language doesn’t, exponential notation might help.
And when dealing with unfamiliar units, take advantage of constant folding to make your numbers self-explanatory.
I hope this article helps you write cleaner, more readable code.
If you found this article useful, subscribe for more tips!