sqrt
MathComputes square root of x in 18-decimal fixed-point.
Avg. gas
197
Max abs. error
1.0e-18
when sqrt(x) < 1
Max rel. error
2.0e-18
when sqrt(x) ≥ 1
Signature
solidity
function sqrt(uint256 x) internal pure returns (uint256 y)Parameters
| Name | Type | Description |
|---|---|---|
| x | uint256 | Input in 18-decimal fixed-point format (1e18 = 1.0). Any value in [0, uint256.max] accepted. |
Returns
| Name | Type | Description |
|---|---|---|
| y | uint256 | Square root √x in 18-decimal fixed-point format. |
Bounds
| Bound | Value |
|---|---|
| Input domain | Full uint256 domain — the function has no named bounds and accepts any input in [0, uint256.max]. The internal branch cutoff at type(uint128).max is an implementation detail, not a limit on callers. |
Behavior
- Returns
0whenx == 0— handled by the algorithm's natural underflow via EVM'sdiv(0, 0) = 0semantic, no explicit guard. - Never reverts. Handles the full
[0, uint256.max]range via a two-branch split attype(uint128).max. - Uses the
CLZopcode (Osaka) inside the range reduction; see Counting leading zeros in Solidity using CLZ opcode. - Pure assembly hot path; no external calls or storage.
How it works
Pre-scale, seed, refine — all in assembly:
// 1. Pre-scale x to 1e36 base so div(x, y) lands in 1e18 — cheap div, no muldiv x := mul(x, 1e18) // 2. CLZ seed: y = 2^floor(msb/2), msb = 256 − clz(x) — within √2 of √x y := shl(shr(1, sub(254, clz(x))), 2) // 3. Five Newton steps — shr halves; quadratic convergence to bit-perfect FP18 y := shr(1, add(y, div(x, y))) // ×5, ~20 gas each
The seed lands within a factor of √2 of the root (~41% worst case); five Newton steps drive that to ~80 bits — bit-exact when √x < 1, under 2e-18 relative error above. A second branch post-scales instead of pre-scaling for x > type(uint128).max, where x · 1e18 would overflow. Full derivation in the walkthrough: How I wrote a fixed-point Solidity sqrt that runs in 197 gas.
Errors
| Error | Trigger |
|---|---|
| None | Never reverts. Accepts any uint256 input. x == 0 returns 0; large x takes the post-scale branch and stays FP18-accurate. |
Example
solidity
import "defimath-lib/contracts/math/Math.sol";
uint256 x = 2e18; // x = 2.0
uint256 y = Math.sqrt(x); // y ≈ 1.41421356e18