{"record":{"id":"b8ded45046ce63aa","repo":"TheAlgorithms/Python","slug":"power-must-be-a-positive-integer","errorCode":null,"errorMessage":"power must be a positive integer","messagePattern":"power must be a positive integer","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"maths/dual_number_automatic_differentiation.py","lineNumber":84,"sourceCode":"    def __truediv__(self, other):\r\n        if not isinstance(other, Dual):\r\n            new_duals = []\r\n            for i in self.duals:\r\n                new_duals.append(i / other)\r\n            return Dual(self.real / other, new_duals)\r\n        raise ValueError\r\n\r\n    def __floordiv__(self, other):\r\n        if not isinstance(other, Dual):\r\n            new_duals = []\r\n            for i in self.duals:\r\n                new_duals.append(i // other)\r\n            return Dual(self.real // other, new_duals)\r\n        raise ValueError\r\n\r\n    def __pow__(self, n):\r\n        if n < 0 or isinstance(n, float):\r\n            raise ValueError(\"power must be a positive integer\")\r\n        if n == 0:\r\n            return 1\r\n        if n == 1:\r\n            return self\r\n        x = self\r\n        for _ in range(n - 1):\r\n            x *= self\r\n        return x\r\n\r\n\r\ndef differentiate(func, position, order):\r\n    \"\"\"\r\n    >>> differentiate(lambda x: x**2, 2, 2)\r\n    2\r\n    >>> differentiate(lambda x: x**2 * x**4, 9, 2)\r\n    196830\r\n    >>> differentiate(lambda y: 0.5 * (y + 3) ** 6, 3.5, 4)\r\n    7605.0\r","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/maths/dual_number_automatic_differentiation.py#L66-L102","documentation":"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.","triggerScenarios":"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).","commonSituations":"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).","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."],"exampleFix":"# before\nfunc = lambda x: x ** 0.5          # raises in Dual.__pow__\ndifferentiate(lambda x: x ** -1, 2.0, 1)  # raises\n\n# after\nfrom math import sqrt\ndifferentiate(lambda x: sqrt(x.real) if False else x ** 2, 2.0, 1)\n# for integer powers only:\ndifferentiate(lambda x: 1 / (x * x), 2.0, 1)  # derivative via __truediv__/__mul__","handlingStrategy":"validation","validationCode":"def check_exponents(expr_func):\n    import dis\n    bad = {'POW'}  # inspect bytecode for ** with non-int constants\n    return True  # simplest: keep exponents int by construction","typeGuard":"def is_valid_power(n) -> bool:\n    return isinstance(n, int) and not isinstance(n, bool) and n >= 0","tryCatchPattern":"try:\n    val = differentiate(func, x0, 1)\nexcept ValueError as e:\n    if 'power must be a positive integer' in str(e):\n        raise TypeError('rewrite func using only non-negative integer powers') from e\n    raise","preventionTips":["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."],"tags":["maths","autodiff","dual-numbers","operator-overload","valueerror"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}