Skip to content

U supports common numbers literals:

:decimal  : 1000
:binary   : 0011
:float    : 3.14
:hexa     : 0xFF
:octal    : 0o102

All number literals prefix starts with the digit zero 0.

Prefix Radix
0d, 0D Decimal (radix 10)
0x, 0X, 0h, 0H hexadecimal (radix 16)
0o, 0O octal (radix 8)
0b, 0B binary (radix 2)

'0d' is useful when you are doing metaprogramming:

# Function that return a formatted number
# '++' => append

:convert : :> "0" ++ format ++ "1234"
Where format could be 'd', 'x', or 'o'. With 0d, the implementation would have included a special case for decimal number like this:

:? format, {
     :- 'decimal', :> "1234"
     :* "0" ++ format ++ "1234"
}

'_' separator

U also supports writing numbers with _ as a separator:

:million  : 1_000_000 // same as 1000000
:binary_3 : 0b0_11    // 0b11
:float    : 3_14.5    // 314.5
:hex      : 0xEE_F    // 0xEEFF
:octal    : 0o10_2    // 0o102

Integer literals

Integer literals are the most basic way to denote numbers. See Above.

Integers literal default is int.

Floating-point literals

Floating-point literals consist in:

  • an integer part
  • a fractional part
  • an exponent part:
    • starts with the character e, p or P
    • is a decimal value by default
    • starts with:
      • px or PX with an hexadecimal value

The fractional part or the exponent part can be omitted but not both, to avoid ambiguity with integer literals.

Decimal Floating-point Literals

The exponent part is interpreted as a power of 10.

Hexadecimal Floating-point Literals

The syntax is similar to that of decimal floating-point literals, with the following differences:

  • The integer part and the fractional part use hexadecimal digits
  • The exponent part:
    • starts with the character p or P, not e to avoid ambiguity with hexadecimal value e.
    • interpreted as a power of 2.

For example, 0xAB.FFp4.

Octal Floating-point Literals

The syntax is similar to that of integer literals, with the following differences:

  • The integer part and the fractional part use octal digits
  • The exponent part in decimal and interpreted as a power of 2.

For example, 0o12.04p4.

As a consequence, the integer and floating-point operators are distinct. E.g., to add integers, use +. To add floating-point numbers, use +..

 bf16 -3.1415, NaN, 2000.0, +Inf

Default size

Please note that int and float is always the size of the target default size: 64, 32, 16, or 8 bits. However, there are helpers to manage low-level data types like i64, f64...

On modern targets, it's 64 bits.

You can also cast a number to another type with the @ aperture:

:a : @:int16 42

Number conversion

In U, all number expressions requires using the same type. However, for convenience, there are exceptions to that rule when a number if promoted (converted) to a larger data range:

flowchart LR i8 --> i16 --> int --> i64 u8 --> u16 --> u32 --> u64 i64 --> pointer char --> int i64 --> f32 --> f64 u64 --> f32 u64 --> pointer

Some conversions are safe and done automatically unless specified in ugo.u, others are not:

  • i8 to i64: no warning unless specified
  • i32 to f64: warning, potential precision loss
  • i64 to u32: error, must explicitly downcast it

Integers literal default is int.

:a : 75                # Type 'int', by default i64
:b : 14.7              # Type 'float, by default f64
:b1 : .001

:c : @:u16 12
:d : 13 + c            # Type 'u16' - no promotion

:e : @:f32 45.6
:g : e + 3.14          # Type 'f32' - no promotion

:h : b + e             # Automatic promotion of 'e'(f32) to 'b'(f64) with warnings

c := e                 # Error, converstion from 'e'(f32) to 'c'(u16)