TheAlgorithms/Python · error · ValueError

Precision must be a nonnegative integer

Error message

Precision must be a nonnegative integer

What it means

The second parameter of bailey_borwein_plouffe() controls how many extra hex digits are computed to stabilize the requested digit. It must be a nonnegative int; anything negative or non-int raises ValueError('Precision must be a nonnegative integer').

Source

Thrown at maths/bailey_borwein_plouffe.py:43

      ...
    ValueError: Digit position must be a positive integer
    >>> bailey_borwein_plouffe(1.7)
    Traceback (most recent call last):
      ...
    ValueError: Digit position must be a positive integer
    >>> bailey_borwein_plouffe(2, -10)
    Traceback (most recent call last):
      ...
    ValueError: Precision must be a nonnegative integer
    >>> bailey_borwein_plouffe(2, 1.6)
    Traceback (most recent call last):
      ...
    ValueError: Precision must be a nonnegative integer
    """
    if (not isinstance(digit_position, int)) or (digit_position <= 0):
        raise ValueError("Digit position must be a positive integer")
    elif (not isinstance(precision, int)) or (precision < 0):
        raise ValueError("Precision must be a nonnegative integer")

    # compute an approximation of (16 ** (n - 1)) * pi whose fractional part is mostly
    # accurate
    sum_result = (
        4 * _subsum(digit_position, 1, precision)
        - 2 * _subsum(digit_position, 4, precision)
        - _subsum(digit_position, 5, precision)
        - _subsum(digit_position, 6, precision)
    )

    # return the first hex digit of the fractional part of the result
    return hex(int((sum_result % 1) * 16))[2:]


def _subsum(
    digit_pos_to_extract: int, denominator_addend: int, precision: int
) -> float:
    # only care about first digit of fractional part; don't need decimal

View on GitHub (pinned to f5988cc097)

Solutions

  1. Pass a plain nonnegative int, e.g. bailey_borwein_plouffe(2, 10).
  2. Wrap computed precisions with int(...) and clamp to >= 0.
  3. Check argument order if you pass position and precision positionally.

Example fix

# before
bailey_borwein_plouffe(2, 1.6)

# after
bailey_borwein_plouffe(2, int(1.6))  # -> precision 1
Defensive patterns

Strategy: validation

Validate before calling

precision = int(max(0, precision)) if precision == int(precision) else None
if precision is None:
    raise ValueError("precision must be a nonnegative integer")

Type guard

def is_valid_precision(p: object) -> bool:
    return isinstance(p, int) and not isinstance(p, bool) and p >= 0

Prevention

When it happens

Trigger: bailey_borwein_plouffe(2, -10); bailey_borwein_plouffe(2, 1.6); passing bool is fine (bool is int), but floats like 8.0 are rejected by isinstance(precision, int).

Common situations: Defaulting precision from a float config value; computing precision as a division result (e.g. n / 2); swapping argument order so a position lands in the precision slot.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/eaa947079a5c5d67. Report an issue: GitHub.