# Herbie: Rewriting Floating-Point Expressions Before They Lose Precision

> Herbie takes an FPCore expression and searches for an algebraically different form that evaluates more accurately in floating point. It is a Racket package with a Rust component, a web interface, and a shell, and it targets people whose numerical code is already written and already wrong at the last few bits.

**herbie-fp/herbie** — Optimize floating-point expressions for accuracy

- Repository: https://github.com/herbie-fp/herbie
- Website: https://herbie.uwplse.org
- Stars: 896 · Forks: 53
- Language: HTML
- License: NOASSERTION
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/herbie-fp-herbie

## The failure Herbie is built to catch

Floating-point error is not evenly distributed. Most expressions are fine. A few lose most of their significant digits to cancellation, and the loss is invisible in the source because the algebra looks correct. The README's own example is the smallest version of this: (FPCore (x) (- (+ 1 x) x)). In exact arithmetic that is 1. In floating point, for large x, the addition of 1 is absorbed and the subtraction returns zero. Herbie answers with 1, which is the value the algebra promised and the hardware does not deliver. That gap is the whole subject of the tool. The audience is narrow on purpose: people writing numerical kernels, library functions, or simulation inner loops who can express the computation as a single expression in FPCore and who care about the last bits rather than the first ones. If your bug is an off-by-one in an index, Herbie has nothing to say.

## Search, not simplification: what happens between input and output

Herbie is not a symbolic simplifier. A simplifier rewrites toward fewer operations; Herbie rewrites toward lower error, and those two goals frequently disagree. The mechanism implied by the repository layout and the README is a generate-and-test loop: the input expression is sampled over its input domain, each candidate rewrite is evaluated on those samples, and the candidate whose error against a high-precision reference is lowest wins. The output is another FPCore expression, not a proof and not a certificate. That distinction matters when you read the result. The rewritten form is a claim about the sampled points, and the documentation's framing of Herbie as improving error rather than guaranteeing it is consistent with that. The search space is algebraic identities, so the tool can return a form that is mathematically equal to your input but numerically unrelated, and it can also return a form that is worse on a region the sampler did not visit. The repository is primarily HTML by language count, which reflects the web interface and documentation rather than the core; the core is Racket with a Rust component, and the source install requires Racket 8.0 or later and Rust 1.87.0 or later.

## Installing from the Racket package archive

The README recommends the package archive over a source checkout. Install Racket, then run raco pkg install --auto herbie. That single command pulls the package and its dependencies. The README states that Windows, Linux, and macOS are supported on both x86 and AArch64. One platform note is given explicitly and is worth repeating because it costs an afternoon to diagnose: on Linux, avoid the Snap installer for Racket. After installation, racket -l herbie starts the tool. If you want the web interface instead, the command is racket -l herbie web. The source route exists for people working on Herbie itself and uses make install from the repository root, with the same Racket and Rust version floors.

## The shell, the batch commands, and the FPCore contract

The interactive path is racket -l herbie shell. The README shows a session banner reading Herbie 1.3 with a seed, a prompt, and the (FPCore (x) ...) input echoed back with the rewritten result. Note the version string in that transcript does not match the current release line, which is at v2.3 as of July 2026; treat the transcript as illustrative of the interface, not of current output. Input is FPCore 1.2, a small S-expression format, and the README points at bench/ in the repository for more examples. Beyond the shell there are two batch commands, improve and report, documented on the options page rather than in the README. That split is a real friction point: the README gets you to a prompt, and everything about non-interactive use, including how to feed a file of expressions and where results land, lives in the online documentation. Budget time to read it before wiring Herbie into anything automated.

## Where the approach stops working

Herbie operates on one expression at a time. Error that accumulates across a loop, a reduction over a large array, or a sequence of dependent updates is outside what a single FPCore rewrite can express, and no amount of search will recover it. There is also a verification burden that the tool does not remove. The output is an expression you must read, and for anything non-trivial you need your own high-precision check on the inputs you actually care about, because the search is driven by sampling and your domain may not be sampled the way you assume. The seed in the shell banner is a hint that the process is stochastic; the README's transcript prints one, which means results can vary between runs. If you need a deterministic, reproducible rewrite for a build pipeline, that variability is a design property to plan around, not a bug to file. Finally, Herbie rewrites expressions, not programs. It will not touch your memory layout, your compiler flags, or your choice of algorithm, and those often dominate the error budget.

## How this differs from a compensated-arithmetic library

The obvious alternative approach is to keep the expression and change the arithmetic: use a compensated summation routine, a double-double type, or a fused multiply-add where available. That route is deterministic, it composes into loops and reductions, and it costs performance in a way you can measure. Herbie makes the opposite trade. It leaves the arithmetic alone and changes the algebra, which means the rewritten expression runs at ordinary speed on ordinary hardware, but the transformation is found by search and applies to one expression rather than a program. Neither is a superset of the other. If your error is in a dot product over a million elements, compensated summation is the right tool and Herbie is not. If your error is in a closed-form formula with catastrophic cancellation in one subterm, Herbie can find a rearrangement that a compensated library would never suggest, because the library does not rewrite your formula.

## Maintenance, licensing, and what the repository does not tell you

The release cadence visible in the material is roughly annual: v2.1 in July 2024, v2.2 in August 2025, v2.3 in July 2026. That is a slow-moving project, which cuts both ways. You are unlikely to be chasing breaking changes every quarter, and you are also unlikely to get a quick fix for a platform quirk. The source install pins two toolchains, Racket 8.0 or later and Rust 1.87.0 or later, so a source build inherits the upgrade obligations of both. The package-archive install hides most of that but still requires a Racket runtime on every machine that runs Herbie. The licence field for this repository is reported as NOASSERTION, meaning no standard licence identifier was detected. That is not a statement about the actual terms; it means you cannot infer them from the metadata. Read the licence file in the repository and confirm the terms with whoever handles licensing at your organisation before shipping anything derived from Herbie's output, and note that the question of whether a machine-generated rewrite carries a copyright interest is separate from the question of the tool's own licence.

## Conclusion

Adopt Herbie if you have a small number of scalar expressions whose accuracy you can state as an FPCore input and whose rewritten form you are willing to read and re-verify. Do not adopt it if you need a drop-in pass over a whole C or Fortran translation unit, or if your error comes from accumulated state rather than a single expression. Before trusting any output, run the same expression through the shell at two or three different seeds and confirm the rewritten form is stable, then check the reported error against a higher-precision evaluation of your own.

## FAQ

### How do I install Herbie?

From the Racket Package Archive: install Racket, then run raco pkg install --auto herbie, and start it with racket -l herbie. Windows, Linux, and macOS are supported on both x86 and AArch64. A source install instead needs Racket 8.0 or later and Rust 1.87.0 or later, followed by make install.

### What does Herbie do to a floating point expression?

It automatically improves the error. In the shell, entering (FPCore (x) (- (+ 1 x) x)), which is (1 + x) - x, returns a rewritten program that evaluates to 1, the correct real-number answer that the naive form does not produce in floating point.

### Is the Herbie container safe to expose?

Not with its defaults. The default command runs the web interface with --public, which the Dockerfile comment says allows the Docker host to interact with the demo and that typical users should not need. It binds port 80, runs two threads, and the image exposes 80.

### What does a Herbie shell session look like?

racket -l herbie shell opens a prompt after printing the version and a seed, points to the project site for help, and says to exit with Ctrl-D. The transcript in the page is from Herbie 1.3, while the current release is 2.3.

### What is egg-herbie in the Herbie repository?

A Rust crate in the egg-herbie directory, built in release mode and installed as a Racket package. The Makefile's clean step removes five package names, including platform specific ones for linux, windows, osx, and macosm1, and tolerates a failure of each.

### What license is Herbie released under?

The repository's license field is not set and the page names no license, though a LICENSE.md file sits at the root of the tree. The project is described as a joint effort of the University of Washington and the University of Utah.

## Sources

- [herbie-fp/herbie on GitHub](https://github.com/herbie-fp/herbie)
- [Issues](https://github.com/herbie-fp/herbie/issues)
- [Project website](https://herbie.uwplse.org)
- [README](https://github.com/herbie-fp/herbie/blob/main/README.md)
- [Releases](https://github.com/herbie-fp/herbie/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/herbie-fp-herbie
