TheAlgorithms/Python · error · ValueError
power must be a positive integer
Error message
power must be a positive integer
What it means
Raised by Dual.__pow__ in maths/dual_number_automatic_differentiation.py when raising a Dual number to a power n that is negative or a float. Automatic differentiation via repeated multiplication (x = self; for _ in range(n-1): x *= self) only works for non-negative integer exponents — fractional powers need the chain rule on the dual part, negative powers need division machinery the class does not implement here.
Source
Thrown at maths/dual_number_automatic_differentiation.py:84
def __truediv__(self, other):
if not isinstance(other, Dual):
new_duals = []
for i in self.duals:
new_duals.append(i / other)
return Dual(self.real / other, new_duals)
raise ValueError
def __floordiv__(self, other):
if not isinstance(other, Dual):
new_duals = []
for i in self.duals:
new_duals.append(i // other)
return Dual(self.real // other, new_duals)
raise ValueError
def __pow__(self, n):
if n < 0 or isinstance(n, float):
raise ValueError("power must be a positive integer")
if n == 0:
return 1
if n == 1:
return self
x = self
for _ in range(n - 1):
x *= self
return x
def differentiate(func, position, order):
"""
>>> differentiate(lambda x: x**2, 2, 2)
2
>>> differentiate(lambda x: x**2 * x**4, 9, 2)
196830
>>> differentiate(lambda y: 0.5 * (y + 3) ** 6, 3.5, 4)
7605.0
View on GitHub (pinned to f5988cc097)
Solutions
- Rewrite the function with integer powers: use multiplication/division instead of negative exponents (x**-2 -> 1/(x*x)).
- Use explicit sqrt from math on the .real part only if you don't need its derivative; otherwise switch to a symbolic/numeric differentiator that supports fractional powers.
- Change float exponents to ints: x ** 2.0 -> x ** 2.
Example fix
# before func = lambda x: x ** 0.5 # raises in Dual.__pow__ differentiate(lambda x: x ** -1, 2.0, 1) # raises # after from math import sqrt differentiate(lambda x: sqrt(x.real) if False else x ** 2, 2.0, 1) # for integer powers only: differentiate(lambda x: 1 / (x * x), 2.0, 1) # derivative via __truediv__/__mul__
Defensive patterns
Strategy: validation
Validate before calling
def check_exponents(expr_func):
import dis
bad = {'POW'} # inspect bytecode for ** with non-int constants
return True # simplest: keep exponents int by construction Type guard
def is_valid_power(n) -> bool:
return isinstance(n, int) and not isinstance(n, bool) and n >= 0 Try / catch
try:
val = differentiate(func, x0, 1)
except ValueError as e:
if 'power must be a positive integer' in str(e):
raise TypeError('rewrite func using only non-negative integer powers') from e
raise Prevention
- Write differentiated functions with integer powers only: x**-2 -> 1/(x*x).
- Avoid sqrt/x**0.5 inside functions passed to this Dual-based differentiator; use a symbolic tool for fractional powers.
When it happens
Trigger: Using x ** -1 or x ** 0.5 on a Dual instance inside a function passed to differentiate(); also x ** True works (bool is int) but x ** 2.0 raises. The guard is n < 0 or isinstance(n, float).
Common situations: Differentiating functions containing sqrt (x**0.5), reciprocal (x**-1), or cube roots; passing a float literal exponent like 2.0 instead of 2; mathematically equivalent rewrites that hide fractional exponents (1/sqrt(x) written as x**-0.5).
Related errors
- differentiate() requires a function as input for func
- differentiate() requires a float as input for position
- differentiate() requires an int as input for order
- Both points must have the same dimension.
- Monogons and Digons are not polygons in the Euclidean space
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/b8ded45046ce63aa.
Report an issue: GitHub.