1

I'd like to print an large integer without the "e+XX" at the end in Python.

For example, when I write:

n = 100
k = 18
result = 1
i = 0

while i < k:
    result = result * (n - i) / (i + 1)
    i += 1

The result is 3.066451080298821e+19, and I would like to have 30664510802988208300.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
Vincent_Cos
  • 23
  • 1
  • 3
  • 2
    Then you should consider performing integer math. – Ignacio Vazquez-Abrams Mar 16 '17 at 16:43
  • `print int(3.066451080298821e+19)` – ZdaR Mar 16 '17 at 16:44
  • 5
    30664510802988208300 is not infinite... – Binyamin Even Mar 16 '17 at 16:45
  • @ZdaR: Using floats will truncate to 56 bits. – Dietrich Epp Mar 16 '17 at 16:47
  • 1
    Adding to @IgnacioVazquez-Abrams: Perhaps you want `result = result * (n - i) // (i + 1)` (floor division), not `result = result * (n - i) / (i + 1);` ("true" division that results in `float`)? (Side-note: Terminating lines with semi-colons is distinctly non-Pythonic; it's allowed, but don't do it unless you're actually putting multiple statements on a single line, which you also shouldn't do, in general) – ShadowRanger Mar 16 '17 at 16:48
  • @ShadowRanger Using `//` doesn't work in this case. It will truncate the fractional value, resulting in the incorrect result. – zephyr Mar 16 '17 at 16:51
  • BTW, semicolons are not necessary at the end of lines in Python unless you're trying to do a bunch of stuff on one line. (The original code had semicolons at the end). – wordsforthewise Mar 16 '17 at 16:55
  • 2
    @zephyr: In this case, none of the divisions have a remainder, so truncation isn't a problem. – user2357112 Mar 16 '17 at 16:55
  • It's unclear if the OP wants floor division or float to int conversion. – farsil Mar 16 '17 at 16:57
  • I think @DietrichEpp forgot to change `n` to 100 and `k` to 18 in the code; the example doesn't run out of the box. Also, there are superfluous semicolons at the end of the first two lines. I would edit it, but it won't let me. – wordsforthewise Mar 22 '17 at 22:50
  • @wordsforthewise: There you go. – Dietrich Epp Mar 22 '17 at 23:27
  • Hm, it's also been marked as a duplicate of the wrong question. If it is a duplicate, it's a duplicate of a different question. – Dietrich Epp Mar 22 '17 at 23:30
  • Yeah, more like a related post than a dupe. You can't use string formatting to fix the issue because floats can't hold the full amount of information. – wordsforthewise Mar 22 '17 at 23:50

2 Answers2

3

If you want an integer, you have to use integer division, // instead of /, as mentioned in @farsil's deleted answer.

result = 1
k = 18
n = 100

for i in range(k):
    result = result * (n - i) // (i + 1)

print(result)

This only gives the correct result if i + 1 is always a divisor of result * (n - i). However, this is always true, so we are fine.

You cannot use / because that will perform floating-point division, which will truncate the results to 56 bits. The correct result does not fit in 56 bits:

In [1]: int(float(30664510802988208300))
Out[1]: 30664510802988208128
#                        ^^^ oops... off by 172

Why is floor division safe?

In this case, when the division by 2 is performed, we have multiplied result by n and n-1, at least one of which is a multiple of 2. When i+1 is 3, then we have multiplied by n, n-1, and n-2, at least one of which is a multiple of 3. This pattern works for all numbers.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • It takes a bit more work than that to really prove it's safe, because directly matching numbers to their multiples might "overcommit" a particular number in the numerator. For example, with n=28 and k=8, we can't match the 24 up to both 8 and 6. – user2357112 Mar 16 '17 at 17:15
  • @user2357112: Yes, that is really just a sketch of a proof, but it is a well-known result. – Dietrich Epp Mar 16 '17 at 17:51
2

I think the question you really want to ask is 'how can I print a number in Python without scientific notation?'

The answer is, your number right now is a float. Try print(type(result)) and you will see it says float. You could type cast it to an integer by doing int(result), and it will show close to the full number, 30664510802988208128. It will be a bit off because of the memory size storage limitations of int vs float.

The better way to do this would be like:

result = 1
i = 0

while i < 18:
    result = result * (100 - i) // (i + 1)
    i += 1

print(result)

which will keep result as an int type. It now should print 30664510802988208300

wordsforthewise
  • 13,746
  • 5
  • 87
  • 117
  • 1
    This doesn't work as Dietrich Epp pointed out in the comments. Python will truncate your float and if your number is large enough, it won't actually match the true int value after you cast it. – zephyr Mar 16 '17 at 16:57
  • Yeah it's a little off as Dietrich said in his answer. – wordsforthewise Mar 17 '17 at 23:35