How Verse Tamed NaN: Three Amendments to IEEE-754
Nearly every language copies the IEEE-754 floating-point standard wholesale, complete with its most famous quirk: NaN equals nothing, not even itself. Verse, unusually, took a scalpel to the standard — three amendments, in exchange for totally ordered, deterministic floats. This piece explains what changed and why it was worth it.
1. Elsewhere, NaN Is a Repeat Offender
NaN (Not a Number) is the accident by-product of floating-point math — divide 0 by 0, take the square root of a negative, and out it comes. The IEEE-754 standard decrees: a comparison between NaN and any value never holds, including a comparison with itself. That decree made NaN a regular on every language's bug charts:
Elsewhere, NaN is notorious trouble. Its deadliest habit: "equal to nothing — not even equal to itself". So you slip a NaN into a pile of data, and later you can't find it no matter what — because finding it means asking "which value equals NaN", and no value equals NaN. Sorting is an even bigger disaster zone: sorting runs on "which is bigger", but NaN meets everything with "neither bigger, nor smaller, nor equal", the foundation caves in, and the same data can come out in different orders. Almost every newcomer on every platform has stepped in this one.
Worse still, in IEEE-754 there isn't even just one NaN — the standard permits a whole crowd of NaNs that look different on the inside to coexist. For a language that writes “determinism” into its design goals, this entire package is unacceptable: the same code with the same input must always produce the same result.
2. Verse's Three Amendments
The official float documentation explicitly lists Verse's departures from IEEE-754 — exactly three:
First, the whole language has exactly one NaN. Whichever accident scene it crawls out of, it is the same value — no extended family of NaNs that all look different on the inside; comparisons and checks finally have a single answer.
Second, NaN equals itself. NaN = NaN is a successful comparison in Verse. The ghost that can't find itself in other languages is, here, a well-behaved ordinary value.
Third, NaN takes part in comparisons — and is greater than every other float. No longer the "third state" of comparison, it sits firmly as the sentinel at the far right end of the number line.
Together, the three buy something called a total order: between any two floats, exactly one of greater, less, or equal must hold. Sorting an array containing NaN always yields a deterministic result, never flaky; Min, Max, binary search — every algorithm that lives off "which is bigger" keeps its assumptions intact. It's the same temperament as two other Verse habits — an assignment either lands whole or is withdrawn whole; when a wire fails to go through, every change it made is rolled back whole. It all boils down to one sentence: better to deviate from the common standard than to break "the same program always computes the same result".
Of course, there is no such thing as a free total order — "NaN is largest" carries one corollary you must remember: if a NaN sneaks into a pile of data, Max will fish it out as the maximum and pollute your stats. Leaderboards, highest-damage records, and logic like that should stop NaN right at the data's front door.
The good news: catching NaN in Verse is actually simpler than in other languages — since NaN equals itself, a plain comparison is the detector:
using { /UnrealEngine.com/Temporary/Diagnostics }
# NaN equals itself, so an equality comparison is the detection tool
# For the exact spelling of the NaN constant, defer to the Verse API Reference
if (Value = NaN):
Print("Caught a NaN, stopping it")
else:
Print("Value looks normal, pass")
Graph translation: a Branch (if) node asks "does Value equal NaN?" — in Verse, if that comparison goes through, the value really is NaN (this move fails elsewhere, since there NaN doesn't equal itself). Goes through: Print String reports "stopping it". Takes the else pin: Print String reports "pass".
Compare: other platforms either hand you a dedicated "is this NaN" function, or lean on the old backwards trick of "a number that doesn't equal itself" — in Verse, one ordinary equality comparison (a single = check) is enough. One boundary note from Lesson 9 while we're here: Verse's float division never fails to go through, and the official docs describe float's possible values as "finite numbers, plus NaN", with not even positive or negative infinity given a seat at the table; but what 1.0 / 0.0 actually produces, the docs don't say — verify in the editor before drawing conclusions.
In Verse, what is the result of the comparison expression NaN = NaN?
A NaN has snuck into a set of player damage values. What does taking their Max return?
Sources
Compiled from the official documentation: Float in Verse (UEFN docs) ↗ · Float in Verse (Fortnite docs) ↗