jax-ml/jax · error · NotImplementedError

integer np.round not implemented for decimals < 0

Error message

integer np.round not implemented for decimals < 0

What it means

jnp.round is a no-op for integer dtypes because integers cannot be rounded to fractional digits. Rounding integer arrays to negative decimals (i.e. rounding to tens/hundreds) is not implemented and raises NotImplementedError.

Source

Thrown at jax/_src/numpy/lax_numpy.py:3481

    >>> jnp.round(x)
    Array([2., 3., 6.], dtype=float32)
    >>> jnp.round(x, decimals=2)
    Array([1.53, 3.27, 6.15], dtype=float32)

    For values exactly halfway between rounded values:

    >>> x1 = jnp.array([10.5, 21.5, 12.5, 31.5])
    >>> jnp.round(x1)
    Array([10., 22., 12., 32.], dtype=float32)
  """
  a = util.ensure_arraylike("round", a)
  decimals = core.concrete_or_error(operator.index, decimals, "'decimals' argument of jnp.round")
  if out is not None:
    raise NotImplementedError("The 'out' argument to jnp.round is not supported.")
  dtype = a.dtype
  if issubdtype(dtype, np.integer):
    if decimals < 0:
      raise NotImplementedError(
        "integer np.round not implemented for decimals < 0")
    return a  # no-op on integer types

  def _round_float(x: ArrayLike) -> Array:
    if decimals == 0:
      return lax.round(x, lax.RoundingMethod.TO_NEAREST_EVEN)

    # TODO(phawkins): the strategy of rescaling the value isn't necessarily a
    # good one since we may be left with an incorrectly rounded value at the
    # end due to precision problems. As a workaround for float16, convert to
    # float32,
    x = lax.convert_element_type(x, np.float32) if dtype == np.float16 else x
    factor = lax._const(x, 10 ** decimals)
    out = lax.div(lax.round(lax.mul(x, factor),
                            lax.RoundingMethod.TO_NEAREST_EVEN), factor)
    return lax.convert_element_type(out, dtype) if dtype == np.float16 else out

  if decimals > np.log10(dtypes.finfo(dtype).max):

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Convert to float before rounding: jnp.round(a.astype(jnp.float32), decimals=-1) (cast back if needed)
  2. For pure integer math to nearest 10: ((a + 5) // 10) * 10
  3. Guard integer inputs to skip the round call when decimals < 0 is not required

Example fix

// before
jnp.round(int_arr, decimals=-1)
// after
jnp.round(int_arr.astype(jnp.float32), decimals=-1).astype(jnp.int32)
Defensive patterns

Strategy: type-guard

Validate before calling

if jnp.issubdtype(a.dtype, jnp.integer) and decimals < 0:
    a = a.astype(jnp.float32)

Type guard

def needs_float_round(a, decimals) -> bool:
    return jnp.issubdtype(a.dtype, jnp.integer) and decimals < 0

Prevention

When it happens

Trigger: jnp.round(jnp.array([123], dtype=jnp.int32), decimals=-1). decimals >= 0 on integers is fine (no-op).

Common situations: Porting NumPy code that rounds integers to significant figures (decimals=-2); generic rounding helpers where dtype is caller-controlled.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/157b9f5b31d51613. Report an issue: GitHub.