2026-04-10 23:27:55 +02:00
---
layout: page
published: true
2026-04-11 00:18:36 +02:00
noToc: false
2026-04-10 23:27:55 +02:00
noComments: false
noDate: false
2026-06-14 22:16:13 +02:00
title: Working with numbers and floats in Fun
2026-04-10 23:27:55 +02:00
subtitle: Working with integers and floats, arithmetic, conversions, clamping, bitwise ops, and patterns.
description: Working with integers and floats, arithmetic, conversions, clamping, bitwise ops, and patterns.
permalink: /documentation/numbers/
lang: en
tags:
2026-04-11 00:18:36 +02:00
- arithmetic
- bitwise
- clamping
- conversions
- floats
- integers
- numbers
- ops
- patterns
2026-04-10 23:27:55 +02:00
---
2026-02-17 14:59:39 +01:00
This guide covers the numeric types in Fun, with a focus on the integer "number" type and the 64‑ bit floating point "float" type. You’ ll find creation, arithmetic, conversion, clamping, bitwise operations, and common patterns.
## TL;DR
- number = signed integer; float = 64‑ bit floating point.
- Use +, -, *, / for arithmetic. If you need fractional results, make at least one operand a float.
- Modulo: a % b. Integer division with / may discard the fractional part; cast to float to preserve it.
- Convert/parse: to_number("123"), to_string(x), cast(x, "float"), cast(x, "number").
- Clamp to widths when interfacing with external code: uclamp(n, bits), sclamp(n, bits).
- Bitwise (numbers only): &, |, ^, ~, <<, >>.
## Numeric types at a glance
- number: signed integer (implementation‑ defined width; use uclamp/sclamp for fixed‑ width interop)
- float: IEEE‑ 754 double precision (64‑ bit)
2026-04-11 02:38:47 +02:00
<pre>an = 42 // number
2026-02-17 14:59:39 +01:00
af = 3.14159 // float
print(typeof(an)) // "number"
2026-04-15 01:25:17 +02:00
print(typeof(af)) // "float"</pre>
2026-02-17 14:59:39 +01:00
## Literals
- Integer (number): 0, 1, -7, 120
- Floating point (float): 0.0, 1.5, -2.75, 1e3, -4.2e-1
2026-04-11 02:38:47 +02:00
<pre>x = 10
2026-02-17 14:59:39 +01:00
y = 2.5
2026-04-15 01:25:17 +02:00
z = -3</pre>
2026-02-17 14:59:39 +01:00
## Arithmetic
Basic arithmetic works as you’ d expect:
2026-04-11 02:38:47 +02:00
<pre>a = 7
2026-02-17 14:59:39 +01:00
b = 2
print(a + b) // 9
print(a - b) // 5
print(a * b) // 14
2026-04-15 01:25:17 +02:00
print(a % b) // 1 (modulo)</pre>
2026-02-17 14:59:39 +01:00
Division and result type:
2026-04-11 02:38:47 +02:00
<pre>// If you need a fractional result, ensure a float is involved
2026-02-17 14:59:39 +01:00
print(7 / 2) // implementation may yield 3 or 3.5 depending on numeric rules
print(cast(7, "float") / 2) // 3.5 (recommended when you need fractions)
2026-04-15 01:25:17 +02:00
print(7 / 2.0) // 3.5</pre>
2026-02-17 14:59:39 +01:00
Mixing numbers and floats promotes the operation to float semantics:
2026-04-15 01:25:17 +02:00
<pre>print(2 + 0.5) // 2.5</pre>
2026-02-17 14:59:39 +01:00
## Comparisons
2026-04-11 02:38:47 +02:00
<pre>print(3 < 5) // 1 (true)
2026-02-17 14:59:39 +01:00
print(3 == 3) // 1
print(3 != 4) // 1
// Be explicit when comparing ints vs floats if types matter
print(1 == 1.0) // may be true, but types differ
2026-04-15 01:25:17 +02:00
print(cast(1.0, "number") == 1) // 1 (true) with explicit cast</pre>
2026-02-17 14:59:39 +01:00
## Conversions and parsing
2026-04-11 02:38:47 +02:00
<pre>n = to_number("123") // 123 (number)
2026-02-17 14:59:39 +01:00
f = cast(n, "float") // 123.0 (float)
n2 = cast(3.9, "number") // 3 (truncation semantics)
2026-04-15 01:25:17 +02:00
print(to_string(f)) // "123"</pre>
2026-02-17 14:59:39 +01:00
If parsing fails (e.g., to_number("abc")), expect a runtime error; guard accordingly.
## Clamping to fixed widths
When interoperating with bytecode, C APIs, or binary formats, clamp integers to a specific bit width.
2026-04-11 02:38:47 +02:00
<pre>// Unsigned clamp to N bits
2026-02-17 14:59:39 +01:00
u8 = uclamp(300, 8) // 44
u16 = uclamp(70000, 16)
// Signed clamp to N bits
2026-04-15 01:25:17 +02:00
s8 = sclamp(-130, 8) // wraps into signed 8‑ bit range</pre>
2026-02-17 14:59:39 +01:00
Choose the bits according to the target field (8, 16, 32, 64). See your interop API docs for exact ranges.
## Bitwise operations (numbers)
Bitwise operators apply to the integer number type.
2026-04-11 02:38:47 +02:00
<pre>a = 0b0110 // if binary literals aren’ t supported in your setup, use decimals: a = 6
2026-02-17 14:59:39 +01:00
b = 0b0011 // or b = 3
print(a & b) // 0b0010 -> 2
print(a | b) // 0b0111 -> 7
print(a ^ b) // 0b0101 -> 5
print(~a) // bitwise NOT (two’ s complement rules)
print(a << 1) // 12
2026-04-15 01:25:17 +02:00
print(a >> 1) // 3</pre>
2026-02-17 14:59:39 +01:00
Note: Bitwise ops are defined for numbers, not floats. Cast floats to numbers first when needed.
## Common patterns
Ensuring float math to avoid unintended truncation:
2026-04-15 01:25:17 +02:00
<pre>avg = cast(sum, "float") / cast(count, "float")</pre>
2026-02-17 14:59:39 +01:00
Safe division with guard against zero:
2026-04-11 02:38:47 +02:00
<pre>num = 10
2026-02-17 14:59:39 +01:00
den = 0
if den == 0 {
print("division by zero")
} else {
print(num / den)
2026-04-15 01:25:17 +02:00
}</pre>
2026-02-17 14:59:39 +01:00
Parsing user input with fallback:
2026-04-11 02:38:47 +02:00
<pre>raw = "not-a-number"
2026-02-17 14:59:39 +01:00
val = 0
// simplistic guard pattern; adapt to your error handling style
if find(raw, "0") >= 0 || find(raw, "1") >= 0 { // crude pre-check
val = to_number(raw)
2026-04-15 01:25:17 +02:00
}</pre>
2026-02-17 14:59:39 +01:00
## Gotchas
- Integer division vs float division: promote to float when you need fractional results.
- Overflow/underflow: clamp explicitly when targeting fixed‑ width fields; otherwise values follow the VM’ s integer semantics.
- Bitwise with negatives uses two’ s complement; ~x equals -(x+1).
## See also
2026-04-15 01:25:17 +02:00
- Core overview: [../types/ ](../types/ )
- Math helpers and advanced ops: check [../opcodes/ ](../opcodes/ ) and the vm/math sources for available functions.
- Strings: [../strings/ ](../strings/ )