What is the complexity of str() function in Python3?

Question:

I have to create a function respecting an O(n) complexity and to do that i want to use the str() function.

Can someone explain me if :

str(1000)

Is this code O(1) or O(4) because of the 1+0+0+0 ?

Asked By: Freddy

||

Answers:

O(n) in the context of a data structure just means if there are n items then an operation on that structure will require (in the order of) n iterations or passes to achieve the desired result. If you’re constructing a string from an integer, then I guess the complexity would be O(log10(n))

EDIT: from the Python docs:

If neither encoding nor errors is given, str(object) returns object.str(), which is the “informal” or nicely printable string representation of object.

Python detects that the object is an int, therefore it will create a string from that int. One way of implementing this conversion is:

if n == 0:
    return "0"
negative = n < 0
if negative:
    n = -n
out = ""
while n > 0:
    digit = n % 10
    n /= 10
    out = chr(48 + digit) + out
if negative:
    out = "-" + out

The number of iterations inside that while loop depends on the number of digits in decimal that n contains, which is log10(n).

Answered By: Jack Bendtsen

The function is used for string conversion. That means converting each of the value into a string. The complexity is depended on the length. If the the full length is n so the complexity will be O(n).
If the size is a fixed number, in this case it will be executed a constant size. We represent the constant as O(1).

Answered By: pr0mila

As can be seen from the source code, the implementation of int.__str__ has runtime complexity of O(m*n) where m is the number of binary digits and n is the number of decimal digits. Since for an integer i the number of digits in an arbitrary base b is given by log(i, base=b) and logarithms in different bases differ only by a constant, the runtime complexity is O(log(i)**2), i.e. quadratic in the number of digits.

This can be verified by running a performance test:

import perfplot

perfplot.show(
    setup=lambda n: 10**n,
    kernels=[str],
    n_range=range(1, 1001, 10),
    xlabel='number of digits',
)

performance plot

The quadratic time complexity in the number of digits is also mentioned in the issue for CVE-2020-10735:

[…] A huge integer will always consume a near-quadratic amount of CPU time in conversion to or from a base 10 (decimal) string with a large number of digits. No efficient algorithm exists to do otherwise.

Answered By: a_guest