Lodash _.round() method

Beginner
⏱️ 6 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.round wraps Math.round via the createRound factory—positive precision means decimals, negative precision means tens / hundreds / thousands.
  • That half-rounding is asymmetric: ties round toward +Infinity, so _.round(-0.5) is -0, not -1. It’s not banker’s rounding.
  • How the exponential-shift trick fixes the famous Math.round(1.005 * 100) / 100 = 1 bug (Lodash returns 1.01).
  • How inputs are coerced: null → 0, undefined → NaN, "5.5" → 5.5; Infinity passes through; BigInt throws.
  • When to reach for _.round vs Number.prototype.toFixed, Intl.NumberFormat, or scale-then-integer-math.

Prerequisites

Read _.ceil() or _.floor() first—all three share the createRound factory, differing only in the Math method they wrap.

  • Native Math.round behaviour: half-toward-positive-infinity. Math.round(-0.5) is -0, not -1.
  • Scientific notation: JavaScript stores numbers as mantissa × 10^exponent; bumping the exponent shifts the decimal point safely.

Overview

The factory createRound('round') returns a function that runs the input through toNumber, clamps the precision via nativeMin(toInteger(precision), 292), then splits the number's scientific form on 'e', bumps the exponent by precision, calls Math.round, and shifts back. The exponent-trick avoids the multiply-divide precision loss that plagues naive rounding.

Half toward +∞

_.round(0.5) = 1; _.round(-0.5) = -0 (not -1). Inherited from Math.round.

Positive / negative precision

Positive → decimals; negative → tens, hundreds, thousands.

Exponent-shift fix

Avoids the classic Math.round(1.005 * 100) / 100 = 1 bug by routing through string × exponent.

Syntax

javascript
_.round(number, [precision = 0])
  • number: the value to round. Coerced via toNumber: strings parse, null0, undefinedNaN.
  • precision (optional, default 0): integer. Positive = decimal places; negative = round to tens / hundreds. Clamped at 292 internally.
  • Returns: number—the rounded value. NaNNaN; ±Infinity passes through.
1

Basics — positive and negative precision

Positive precision rounds to n decimal places. Negative precision rounds to the nearest 10|n|. The official docs example covers all three modes.

javascript
import round from "lodash/round";

console.log(round(4.006));                  // 4         (docs example)
console.log(round(4.006, 2));               // 4.01      (docs example)
console.log(round(4060, -2));               // 4100      (docs example)

// Common usage
console.log(round(5.678, 1));               // 5.7
console.log(round(3.14159265358979, 5));    // 3.14159
console.log(round(1234.56789, 2));          // 1234.57

// Negative precision = round to nearest 10^|n|
console.log(round(9876543210.123, -5));     // 9876500000  (NOT 9876543210)
console.log(round(1234, -3));                // 1000
Try it Yourself
2

Half-rounding is asymmetric

Ties don’t go to the nearest even number (that’s “banker’s rounding”) and they don’t go away from zero either. They go toward positive infinity. So positive halves round up, but negative halves round toward zero.

javascript
import round from "lodash/round";

// Positive halves: round up
console.log(round(0.5));     // 1
console.log(round(1.5));     // 2
console.log(round(2.5));     // 3  (NOT 2 like banker's rounding would give)

// Negative halves: round toward zero
console.log(round(-0.5));    // -0  (NOT -1)
console.log(round(-1.5));    // -1
console.log(round(-2.5));    // -2  (NOT -3 like "round half away from zero")

// Mid-decimal half
console.log(round(2.345, 2)); // 2.35
Try it Yourself
3

Why _.round beats Math.round on precision

1.005 isn’t really stored as 1.005—it’s 1.00499999999999989…. So Math.round(1.005 * 100) / 100 rounds down to 1. Lodash sidesteps the multiply-divide round-trip by shifting the exponent in the string form, which is why _.round(1.005, 2) correctly returns 1.01.

javascript
import round from "lodash/round";

// Native naive rounding loses the half
console.log(Math.round(1.005 * 100) / 100);   // 1     (BUG)
console.log(round(1.005, 2));                  // 1.01  (correct)

// _.round handles 0.1 + 0.2 cleanly at sensible precisions
console.log(0.1 + 0.2);                        // 0.30000000000000004
console.log(round(0.1 + 0.2, 1));              // 0.3

// Input coercion (toNumber)
console.log(round(undefined));                 // NaN
console.log(round(null));                       // 0
console.log(round("5.5"));                      // 6
console.log(round(Infinity, 2));                // Infinity
console.log(round(NaN, 2));                     // NaN

// BigInt throws
try {
  console.log(round(1n, 2));
} catch (err) {
  console.log("Threw:", err.message);          // "Cannot convert a BigInt value to a number"
}
Try it Yourself

📋 _.round vs Math.round vs toFixed

Input_.round(n, p)Math.round(n * 10^p) / 10^pn.toFixed(p)Notes
1.005, 21.011"1.00"Only Lodash gets the “intuitive” answer; others suffer FP precision loss.
2.5, 033"3"All three round halves toward +∞ in Node; toFixed may differ across browsers.
-0.5, 0-0-0"0"-0.5 rounds to -0, not -1.
4060, -241004100errortoFixed doesn’t support negative digits.
Return typenumbernumberstringUse toFixed when you want trailing zeros preserved for display.

Pitfalls to avoid

Half rule

Not banker’s, not symmetric

If you expected _.round(2.5) to be 2 (banker’s) or _.round(-2.5) to be -3 (away-from-zero), you’ll be surprised. It’s “half toward +∞” in both cases.

Negative precision

Reads “round to the nearest 10|n|

_.round(9876543210, -5) is 9876500000, not 9876543210. The reference page for this function in many tutorials gets this wrong—verify empirically.

Currency

Still IEEE-754

The exponent-shift fixes 1.005-style traps but not every floating-point quirk. For money, scale to cents and do integer math, or use a decimal library.

Display

Returns a number

_.round(1.20, 2) is 1.2 (the trailing zero is lost). If you need "1.20" for display, use .toFixed(2) on the rounded value or use Intl.NumberFormat.

BigInt

Throws

BigInt is already an integer; rounding doesn’t apply. Convert with Number(bigint) first if you really need the round trip.

❓ FAQ

It rounds toward positive infinity (inherited from Math.round). So _.round(0.5) is 1, _.round(-0.5) is -0, _.round(2.5) is 3, _.round(-2.5) is -2. This is NOT banker's rounding (half-to-even). If you need that, write a custom helper or use Intl.NumberFormat with roundingMode: 'halfEven'.
For some cases, yes. _.round(1.005, 2) returns 1.01 correctly, even though Math.round(1.005 * 100) / 100 returns 1 due to floating-point storage. The trick is the exponential-shift inside createRound: it stringifies the number and bumps its exponent before calling Math.round, avoiding the multiply-then-divide precision loss.
Rounds to the nearest 10^|precision|. _.round(4060, -2) is 4100; _.round(1234, -3) is 1000. The same exponential-shift mechanism applies, just in the other direction.
toNumber coerces the input: null becomes 0, undefined becomes NaN, '5.5' becomes 5.5. So _.round(null) is 0, _.round(undefined) is NaN, _.round('5.5') is 6. The precision argument uses toInteger and clamps at 292.
No—it throws Cannot convert a BigInt value to a number. BigInt is already an integer, so rounding doesn't apply anyway. Use Number(bigint) first if you really need it.
_.round returns a number; .toFixed returns a string. _.round(2.5) is 3 (number); (2.5).toFixed(0) is '3' (string). Use _.round when downstream code expects numeric arithmetic, .toFixed when you need a display string with trailing zeros preserved.

Summary

  • Purpose: round to a configurable precision; thin wrapper over Math.round with an exponent-shift to dodge float quirks.
  • Remember: half-toward-+∞ (not banker’s), positive precision = decimals, negative = tens / hundreds; null0, undefinedNaN; BigInt throws.
  • Next: Lodash _.subtract(), or read the official Lodash docs for _.round.
Did you know?

_.round(1.005, 2) returns 1.01, but naive Math.round(1.005 * 100) / 100 returns 1—the famous JavaScript rounding bug. _.round sidesteps it by stringifying the number and shifting its exponent ('1.005e0' → '1.005e2') before calling Math.round.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful