Overview
Ruby provides extensive support for numeric literals in multiple formats and bases. The language handles two primary numeric types through dedicated classes: Integer
for whole numbers and Float
for decimal numbers. Ruby's numeric system supports literals in decimal (base 10), binary (base 2), octal (base 8), and hexadecimal (base 16) formats.
Integer literals can be written as simple digits, with underscores for readability, or with prefixes to indicate different number bases. Float literals use decimal point notation and can include scientific notation for very large or small numbers.
# Basic integer and float literals
integer = 42
float = 3.14
large_number = 1_000_000
scientific = 1.5e10
# Different number bases
binary = 0b1010 # Binary: 10 in decimal
octal = 0o755 # Octal: 493 in decimal
hex = 0xFF # Hexadecimal: 255 in decimal
Ruby automatically chooses the appropriate internal representation and provides methods for converting between different bases and formats. The language handles arbitrarily large integers without overflow, automatically promoting to Bignum
when needed.
Basic Usage
Integer Literals
Integer literals in Ruby can be written in several ways. The most common form uses standard decimal notation:
positive = 123
negative = -456
zero = 0
# Underscores improve readability for large numbers
million = 1_000_000
billion = 1_000_000_000
Float Literals
Floating-point literals require a decimal point or scientific notation:
simple_float = 3.14
small_decimal = 0.001
large_float = 123.456
# Scientific notation
speed_of_light = 2.998e8 # 299,800,000
planck_constant = 6.626e-34 # 0.0000000000000000000000000000000006626
Binary Literals (Base 2)
Binary literals use the 0b
prefix followed by digits 0 and 1:
binary_eight = 0b1000 # 8 in decimal
binary_flags = 0b11110000 # 240 in decimal
binary_mask = 0b1111 # 15 in decimal
# Binary representation of file permissions
read_write = 0b110 # 6 in decimal (rw-)
executable = 0b001 # 1 in decimal (--x)
full_permissions = 0b111 # 7 in decimal (rwx)
Octal Literals (Base 8)
Octal literals use the 0o
prefix (or just 0
in older Ruby versions):
octal_permission = 0o755 # 493 in decimal (rwxr-xr-x)
octal_value = 0o123 # 83 in decimal
octal_zero = 0o0 # 0 in decimal
# Traditional Unix file permissions
owner_rw = 0o600 # 384 in decimal
world_readable = 0o644 # 420 in decimal
executable_script = 0o755 # 493 in decimal
Hexadecimal Literals (Base 16)
Hexadecimal literals use the 0x
prefix with digits 0-9 and letters A-F:
hex_color = 0xFF0000 # Red: 16711680 in decimal
hex_byte = 0xFF # 255 in decimal
hex_memory = 0x1000 # 4096 in decimal
# Common hexadecimal values
max_byte = 0xFF # 255
hex_kilobyte = 0x400 # 1024
hex_address = 0xDEADBEEF # 3735928559
Advanced Usage
Numeric Conversion Methods
Ruby provides methods to convert numbers between different representations:
number = 42
# Convert to different base strings
binary_string = number.to_s(2) # "101010"
octal_string = number.to_s(8) # "52"
hex_string = number.to_s(16) # "2a"
hex_upper = number.to_s(16).upcase # "2A"
# Parse strings in different bases
parsed_binary = "101010".to_i(2) # 42
parsed_octal = "52".to_i(8) # 42
parsed_hex = "2a".to_i(16) # 42
Working with Bit Operations
Numeric literals work naturally with bitwise operations:
# Bitwise operations with different literal formats
flags = 0b11110000
mask = 0x0F
result = flags & mask # Bitwise AND
combined = 0b1010 | 0b0101 # Bitwise OR: 15
flipped = ~0b1010 # Bitwise NOT
shifted = 0b1010 << 2 # Left shift: 40 (0b101000)
Range Operations with Numeric Literals
Ruby ranges work seamlessly with numeric literals in different bases:
# Ranges using different literal formats
binary_range = (0b1000..0b1111) # 8 to 15
hex_range = (0x10..0x1F) # 16 to 31
octal_range = (0o10..0o17) # 8 to 15
# Iterating over ranges
hex_range.each { |n| puts "0x#{n.to_s(16).upcase}" }
# Output: 0x10, 0x11, 0x12, ... 0x1F
Complex Numeric Expressions
Combining different literal formats in mathematical operations:
# Mixed base arithmetic
result = 0xFF + 0b11111111 + 0o377 # All equal 255, sum is 765
percentage = 0x64 # 100 in hex
fraction = percentage / 100.0 # Convert to float for division
# File permission calculations
owner_perms = 0o700 # rwx------
group_perms = 0o050 # ---r-x---
other_perms = 0o005 # -----r-x
combined_perms = owner_perms | group_perms | other_perms # 0o755
Common Pitfalls
Leading Zero Confusion
One of the most common mistakes involves leading zeros in numeric literals:
# DANGER: Leading zeros create octal numbers in older Ruby
wrong_month = 08 # SyntaxError: Invalid octal digit
wrong_day = 09 # SyntaxError: Invalid octal digit
# Correct approaches
correct_month = 8 # Decimal 8
explicit_octal = 0o10 # Octal 10 (decimal 8)
string_month = "08" # Keep as string if zero-padding needed
Float Precision Issues
Floating-point representation can lead to unexpected results:
# Precision problems with float literals
sum = 0.1 + 0.2 # 0.30000000000000004, not 0.3
comparison = (0.1 + 0.2) == 0.3 # false
# Solutions for precision-critical calculations
require 'bigdecimal'
precise_sum = BigDecimal('0.1') + BigDecimal('0.2') # Exact decimal
tolerance = (0.1 + 0.2 - 0.3).abs < 1e-10 # true
Base Conversion Edge Cases
Converting between bases can produce unexpected results:
# Large numbers and string conversion
large_hex = 0xFFFFFFFFFFFFFFFF
hex_string = large_hex.to_s(16) # "ffffffffffffffff"
# Negative numbers in different bases
negative = -10
binary_negative = negative.to_s(2) # "-1010", not two's complement
hex_negative = negative.to_s(16) # "-a"
# Handling invalid characters in parsing
begin
invalid = "1G".to_i(16) # 1, stops at invalid character
strict_parse = Integer("1G", 16) # ArgumentError
rescue ArgumentError => e
puts "Invalid hexadecimal format"
end
Type Coercion Gotchas
Mixed operations between integers and floats:
# Integer division vs float division
int_division = 5 / 2 # 2 (integer result)
float_division = 5 / 2.0 # 2.5 (float result)
mixed_division = 5.0 / 2 # 2.5 (float result)
# Unexpected type promotion
hex_int = 0xFF # Integer
result = hex_int + 0.1 # Float (255.1)
back_to_int = result.to_i # 255, loses decimal portion
Memory and Performance Considerations
Very large numeric literals can impact memory usage:
# Ruby automatically handles big integers
huge_number = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
puts huge_number.class # Integer (automatically uses Bignum)
# Binary string representations for large numbers
binary_rep = huge_number.to_s(2) # Very long string
memory_usage = binary_rep.bytesize # Significant memory usage
Reference
Integer Literal Formats
Format | Prefix | Valid Digits | Example | Decimal Value |
---|---|---|---|---|
Decimal | None | 0-9 | 123 |
123 |
Binary | 0b |
0-1 | 0b1111 |
15 |
Octal | 0o |
0-7 | 0o755 |
493 |
Hexadecimal | 0x |
0-9, A-F | 0xFF |
255 |
Float Literal Formats
Format | Example | Description |
---|---|---|
Decimal | 3.14 |
Standard decimal notation |
Scientific | 1.5e10 |
Exponential notation |
Negative Exponent | 6.626e-34 |
Small number notation |
Conversion Methods
Method | Parameters | Returns | Description |
---|---|---|---|
#to_s(base) |
base (2-36) |
String |
Convert number to string in specified base |
String#to_i(base) |
base (2-36) |
Integer |
Parse string as integer in specified base |
Integer(string, base) |
string , base |
Integer |
Strict parsing with error checking |
#to_f |
None | Float |
Convert to floating-point |
Common Constants
Constant | Value | Description |
---|---|---|
Float::INFINITY |
Infinity |
Positive infinity |
Float::NAN |
NaN |
Not a number |
Float::EPSILON |
2.220446049250313e-16 |
Smallest representable difference |
Bitwise Operators
Operator | Name | Example | Result |
---|---|---|---|
& |
AND | 0b1100 & 0b1010 |
0b1000 (8) |
| |
OR | 0b1100 | 0b1010 |
0b1110 (14) |
^ |
XOR | 0b1100 ^ 0b1010 |
0b0110 (6) |
~ |
NOT | ~0b1010 |
-11 (two's complement) |
<< |
Left shift | 0b1010 << 2 |
0b101000 (40) |
>> |
Right shift | 0b1010 >> 1 |
0b101 (5) |
Error Types
Error | When Raised | Example |
---|---|---|
SyntaxError |
Invalid literal format | 08 , 0b2 , 0xG |
ArgumentError |
Invalid base in conversion | Integer("FF", 8) |
FloatDomainError |
Invalid float operation | Math.sqrt(-1) |