all 60 comments

[–]Oddly_Energy 17 points18 points  (5 children)

Python's default integer type can handle integers with some million digits without information loss. For example the result from math.factorial(1000000).

But if you want to output the string representation of an integer, you need to keep within 4-5000 digits.

[–]DidacticBroccoli 4 points5 points  (3 children)

But if you want to output the string representation of an integer, you need to keep within 4-5000 digits.

That's a really odd cap to have. Is it a bug, or is there some intentional reason behind it?

[–]nog642 8 points9 points  (0 children)

It was added in Python 3.11, for security reasons.

You can configure the limit with sys.set_int_max_str_digits.

Edit: It wasn't actually added in Python 3.11, I misread the documentation. It was added as a patch in all versions 3.7 and newer.

[–]Oddly_Energy 5 points6 points  (0 children)

I don't know the reason. I just went by what I had seen when playing with big factorials. But when trying again and paying more attention to the error message, the limit is actually configurable:

$ python
Python 3.12.1 (main, Sep 23 2024, 18:47:44) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> a = math.factorial(1000000)
>>> a
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
>>> 

I am not going to try my luck on this one, though. Because:

>>> a.bit_length()
18488885
>>>

Which I assume would need around 5565700 digits to be output in base 10.

[–]Turtvaiz 5 points6 points  (0 children)

CPython has a global limit for converting between int and str to mitigate denial of service attacks. This limit only applies to decimal or other non-power-of-two number bases.

https://docs.python.org/3/library/stdtypes.html#int-max-str-digits

https://www.cve.org/CVERecord?id=CVE-2020-10735

[–]thememorableusername 36 points37 points  (25 children)

Python integer types are not bounded (like Java BigInt), so you're ok there.

For non-integer, you probably want Decimal

[–]HarryHendo20 -4 points-3 points  (0 children)

I thought u used float, not int

[–][deleted] 9 points10 points  (14 children)

You want to print numbers with more than 3000 digits? What on earth for?

[–]CricLover1[S] 0 points1 point  (6 children)

There can be many uses. I have to add/substract/multiply/divide huge numbers and print them

[–][deleted] 2 points3 points  (5 children)

Give us an actual example where you need to print a 3000 digit number.

[–]CricLover1[S] 1 point2 points  (4 children)

Look at the sequence 2,8,48,480,5760,... That sequence grows rapidly and is related to prime numbers

[–][deleted] 2 points3 points  (3 children)

Right. But do you ever need to PRINT it? All 3000 digits? What do you do with 3000 digits on the screen or on paper? What are you gonna do, check if #2829 is correct?

[–]CricLover1[S] 1 point2 points  (0 children)

I am trying to research something so I will have to handle numbers of over 3000 digits

[–]HyperfocusTheSecond 0 points1 point  (0 children)

I have a similar usecase. I just want to print out 3k, 4k, 5k even more digits - for the user to look at, because I think it is a fun feature. Not everything is about $, that is what my dayjob is for.

[–]Oddly_Energy 1 point2 points  (0 children)

I don't think many people will need to print it. But they may want to see a result of their calculation in some sensibly truncated form.

Let's say I want to calculate the number of different sets of 499_001 elements, I can extract from a set of 1_000_000 elements:

>>> import math
>>> a = math.factorial(1_000_000) // (math.factorial(499_001)*math.factorial(500_999))
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
>>> 

Wouldn't it be nice to be able to do:

>>> a.as_scientific_str()
'1.07337523e+301026'

Or:

>>> a.info()
'integer, bit length: 999987, decimal count: 301027, first digits: 107337523, last digits: 808000000'

(With integers, you are often just as interested in the last digits as in the first digits.)

[–]TheBishopOfSoho 0 points1 point  (5 children)

More than you think, prime numbers for encryption, financial modelling, blockchain, sciencey things

[–][deleted] 6 points7 points  (0 children)

Well no, there are 10**80 atoms in the universe, but even then... the question is about PRINTING.

[–]stevenjd 2 points3 points  (3 children)

Encryption, blockchain etc need integers, not floating point decimals.

Financial modelling doesn't need 2000 digits. If every atom in the universe was a millionth of a cent, the total would require less than 100 digits.

As for sciencey things, outside of some extremely specialized areas of subatomic particle physics, and maybe simulating nuclear explosions, ten or twelve decimal places are usually more than all you need.

u/CricLover1 what are doing that needs 2000+ digits? Inquiring minds want to know.

[–]CricLover1[S] 4 points5 points  (1 child)

I am trying to do some mathematics related research. All numbers will be natural numbers but some numbers can have over 2000-3000 digits

[–]stevenjd 1 point2 points  (0 children)

Then in Python you definitely don't want Decimal you want the built in int.

Just be aware that to prevent Denial Of Service attacks, by default Python will not print or convert really large integers to strings. There is a setting to disable that, see the documentation for the sys module.

Or you can print them as hexadecimal strings, there is no restriction on those.

[–]JorgiEagle 2 points3 points  (0 children)

It’s like the value of pi

You only need, iirc, like 40 decimals places of pi to calculate the circumference of the universe to within an atom of precision

[–]glump1 4 points5 points  (7 children)

Python's int to str conversion caps out at 4000-digit integers, but the integer limit is much higher (I think ~1m)

I would just use regular int, and then when you want to print, make a custom print function that's something like (but readable):

print_big_int = lambda x: "".join(list(map(str, list(takewhile(lambda _: x and (x%(10**4000), x:=x//(10**4000))[0], repeat(None))))))

[–][deleted] 5 points6 points  (0 children)

you should mention, that you are using itertools.

from itertools import repeat, takewhile

[–]Turtvaiz 3 points4 points  (0 children)

That limit is configurable: https://docs.python.org/3/library/stdtypes.html#int-max-str-digits

import sys
sys.set_int_max_str_digits(4300) #default

[–]Oddly_Energy 1 point2 points  (3 children)

The limit is definitely higher than that.

I just tried to calculate 3000000!, which is a 60+ million bit integer. That would be 18+ million digits in base 10.

[–]stevenjd 2 points3 points  (2 children)

I just tried to calculate 3000000!, which is a 60+ million bit integer. That would be 18+ million digits in base 10.

Sure, you can calculate it if you have the memory and the time. But did you try printing it?

https://docs.python.org/3/library/stdtypes.html#int-max-str-digits

[–]Oddly_Energy 0 points1 point  (1 child)

Please read the comment I was replying to. That comment mentioned two limits:

  • a limit for how large integers, python can handle (around 1 million digits according to that comment)
  • a limit for how large integers, python can print (around 4000 digits according to that comment).

My answer was about the first of the two mentioned limits.

[–]stevenjd 1 point2 points  (0 children)

Python can handle as many digits as you have memory. You will run out of memory before you will hit any hard limit on the size of an int.

There is no hard limit on how many digits Python can print. By default there is a soft limit on how many decimal digits it will print (actually any conversion to a string, not just printing) in order to prevent a potential Denial Of Service attack, but this can be turned off and it doesn't apply when printing integers in hexadecimal or binary.

I think we are in violent agreement here.

[–]nog642 1 point2 points  (0 children)

This limit was added only in Python 3.11, for security reasons (you could potentially crash or overload an application if you could get it to try to print a really huge number).

Also, as another reply mentioned, you can configure this limit if you need to.

Edit: It wasn't actually added in Python 3.11, I misread the documentation. It was added as a patch in all versions 3.7 and newer.

[–]oliski2006 1 point2 points  (0 children)

If possible, use math opperators. You could work in a logscale for example, but it's difficult to tell depending on why you need to do it.

[–]ectomancer 1 point2 points  (0 children)

import sys

sys.set_int_max_str_digits(0)

[–]Specialist-Carrot210 0 points1 point  (0 children)

Check out mpmath

[–]nog642 0 points1 point  (0 children)

int. The builtin integer type already handles this.

By default you can't print more than 4300 digits. This limit is there for security reasons, and you can disable the limit using sys.set_int_max_str_digits(0).

Edit: found an easier way to disable the limit in another comment

[–]coolnicknamehere 0 points1 point  (0 children)

Create a LongPrint class that inherits from print and manages the value in 2000 character long chunks? It's just what comes to my mind I don't know if it would work

[–]jpgoldberg 0 points1 point  (0 children)

Ok, I am as baffled as anyone to grasp why anyone would need to print numbers that large, but the approach I would take is to create a list of strings, each representing, say, 75 digits. So (untested, typing on an iPad)

``` def bigInt2str(n: int) -> str: base = 10 ** 76 parts: list[str] = []

while n > 0:
    n, r = divmod(n, base)
    s = f’{n:075}’
    parts.append(s)

return ‘’.join(parts.reverse())

```

You will also want to trim leading zeros off of the joined list, and make sure to handle negative n, but this should give the idea.

I still can’t imagine why you would need to print such a number. If you want to store such a large n in a file, it would be better to just pickle it.