270: Hexadecimal Floating-Point Constants

by Peter McGoron

Status

This SRFI is currently in draft status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-270@nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.

Abstract

Floating-point numbers are generally in radix 2, but are written by users in radix 10. This SRFI introduces Scheme syntax for hexadecimal floating point constants based on C99's syntax.

Rationale

Computers generally use binary floating point to store numbers, while humans like decimals. To express binary floating point exactly, one can use hexadecimal floating point constants, which are written in base 16 instead of base 10. They represent binary floating point numbers of any mantissa and exponent size precisely.

Prior art: MIT Scheme supports a version of this syntax. C99 introduced a hexadecimal floating point syntax that was then adopted in IEEE 754-2008.

Specification

Non-normative text is in small text.

Syntax

The following is written in Scheme's BNF, extended with the following: ⟨thing⟩? means zero or one of ⟨thing⟩.

The formal syntax of Scheme is modified to have the following new productions:

⟨ureal R
::= ⟨hex float body R⟩ ⟨hex float suffix⟩
⟨hex float body 16⟩
::= ⟨uinteger 16⟩
| . ⟨digit 16⟩+
| ⟨digit 16⟩+ . ⟨digit 16⟩*
⟨hex float suffix⟩
::= p ⟨sign⟩? ⟨digit 10⟩+

Without an exactness prefix, a hex float is read as an inexact number. Like all numbers, hex floats can be read as exact numbers by prefixing them with #e.

The exponential separator is p because it is ambiguous whether e would be a decimal separator or a hex digit.

A hexadecimal floating point number is interpreted such that

xnxn−1x0.x−1x−2x−mpd

where each x is a hexadecimal digit and d is a base 10 number, is equal to

(Xn×16n + Xn−1×16n−1 + … + X0 + X−1×16−1 + X−2×16−2 + … + X−m×16m)×2d

where Xi is the numerical value of the digit xi.

R6RS Version

On R6RS systems, the above grammar is modified to be:

⟨ureal R⟩
::= ⟨hex float body R⟩ ⟨hex float suffix⟩ ⟨mantissa width⟩
⟨hex float suffix⟩
::= ⟨hex exponent marker⟩ ⟨exponent marker⟩? ⟨sign⟩? ⟨digit 10⟩+
⟨hex exponent marker⟩
::= p
| P

The R6RS considerations for numbers with ⟨exponent marker⟩ and ⟨mantissa width⟩ apply here.

This grammar is a superset of the previous grammar.

Procedures

The procedure string->number must understand hexadecimal floats.

(write-hexadecimal-float x [port])

Write an inexact real as a floating point number. If the number is represented by an IEEE 754 binary floating point number, then the number must be represented in a canonical form. If the number is a real, then:

If the number is complex, then each component must be printed with the above rules.

Examples

This section is non-normative.

Expression Number
#x9p9 9×29 = 4608
#x1.2p3 (1 + 2×16−1)×23 = 9
#xFE.FFp1 (15×161 + 14 + 15×16−1 + 15×16−2)×21 = 1044465/2048 ≈ 509.992…
#x-0.Ap-2 (10×16−1)×2−2 = −5/32 = −.15625
#x1.2p3+10p1i 9+256i

Implementation

A portable implementation is impossible, as it depends on both modifying the reader and knowing the specific representation of inexact reals.

An implementation-specific version will be written.

Acknowledgements

Taylor Campbell suggested it to me on #scheme.

© 2026 Peter McGoron.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Editor: Arthur A. Gleckler