Python Comparing Large Numbers - python

How does one compare large numbers python?
I have the following two numbers:
x = 99 ^ 85, y = 73 ^ 62.
Computing both numbers in the python interpreter gives the following results:
>>> x = 99 ** 85
>>> x
42559012338865490805205255842468783301592970011660094241731171697575386634867177511754750618655432231509140219114042806178869109409115320236642740915044006252790234308499
>>> y = 73 ** 62
>>> y
33575100975948386797110696048991269305533302609246066947133332393856972076850553634350302934134549900847114729991729
Even without computing the results it's quite obvious that x will be greater than y. I performed mod 1000000007 on both numbers in order to reduce the number of digits. I got the following results:
>>> mod = 1000000007
>>> x % mod
195405172
>>> y % mod
297675700
>>>
As you can see the mod results of the numbers results in y being greater than x. Is there an efficient of comparing large numbers and get the right results. I don't think this problem is bound to python alone though the context of the question is under python.
Thanks in advance

Please see this question How does % work in Python?
Modulo give you the remainder of a number. So 4 % 10 = 4 and 14 % 10 = 4. So for directly comparing two numbers you will lose information by using modulo.
Comparing large numbers is pretty quick in python. Use ipython's %timeit to see.
%timeit (99 ** 85)>( 73 ** 62 )
On my system ( an older i7, 14 GB of ram) it took 46.3 nano seconds which is about as fast as any operation in python.

The 'size' of the number have a very small influence in term of execution :
'big numbers' :
>>> timeit.timeit('a=99**85; b=73**52; a>b')
0.07298588752746582
'small numbers':
>>> timeit.timeit('a=5**2; b=6**3; a>b')
0.07102680206298828
If the question is how to compare numbers in python use > and < :
>>> 5>9
False
>>> 5<9
True

Related

Why does this code not give the correct result for Project Euler Question #56?

I'm completing the 56th question on Project Euler:
A googol (10100) is a massive number: one followed by one-hundred zeros; 100100 is almost unimaginably large: one followed by two-hundred zeros. Despite their size, the sum of the digits in each number is only 1.
Considering natural numbers of the form, ab, where a, b < 100`, what is the maximum digital sum?
I wrote this code, which gives the wrong answer:
import math
value = 0
a = 1
b = 1
while a < 100:
b = 1
while b < 100:
result = int(math.pow(a,b))
x = [int(a) for a in str(result)]
if sum(x) > value:
value = sum(x)
b = b + 1
a = a + 1
print(value)
input("")
My code outputs 978, whereas the correct answer is
972
I already know the actual approach, but I don't know why my reasoning is incorrect. The value that gives me the greatest digital sum seems to be 8899, but adding together each digit in that result will give me 978. What am I misinterpreting in the question?
math.pow uses floating point numbers internally:
Unlike the built-in ** operator, math.pow() converts both its arguments to type float.
Note that Python integers have no size restriction, so there is no problem computing 88 ** 99 this way:
>>> from math import pow
>>> pow(88, 99)
3.1899548991064687e+192
>>> 88**99
3189954899106468738519431331435374548486457306565071277011188404860475359372836550565046276541670202826515718633320519821593616663471686151960018780508843851702573924250277584030257178740785152
And indeed, this is exactly what the documentation recommends:
Use ** or the built-in pow() function for computing exact integer powers.
The result computed using math.pow will be slightly different, due to the lack of precision of floating-point values:
>>> int(pow(88, 99))
3189954899106468677983468001676918389478607432406058411199358053788184470654582587122118156926366989707830958889227847846886750593566290713618113587727930256898153980172821794148406939795587072
It so happens that the sum of these digits is 978.

How does Python pow() function work with a negative power and a mod value

The documentation about the pow(base, exp[, mod]) function says,
"If mod is present and exp is negative, base must be relatively prime to mod. In that case, pow(inv_base, -exp, mod) is returned, where inv_base is an inverse to base modulo mod."
I don't understand the line at all and also how it works. The provided example is as follows:
>>> pow(38, -1, mod=97)
23
>>> 23 * 38 % 97 == 1
True
Shouldn't it behave like (38**-1)%97 = 0.02631578947368421 ?
If I try to go from 23 * 38 % 97 == 1 to backward, I don't know what's the inverse of modulo.
Can anyone kindly give me a clear explanation of how it ended being 23? A mathematical explanation will be highly helpful.
In modular arithmetic division does not have a unique answer, so we do not have a division operation. Instead you have modular inverses.
The docs are trying to explain that pow(b, -1, mod=m) can be used to calculate the inverse of b, modulo m. That is, finding some number d such that d * b % m = 1.
The line 23 * 38 % 97 == 1 is simply demonstrating that the answer 23, which was the result of pow(38, -1, mod=97), is the correct modular inverse of 38.
The explanation in the docs seems to be assuming the reader already has some familiarity with modular arithmetic.
Can anyone kindly give me a clear explanation of how it ended being 23? A mathematical explanation will be highly helpful.
Try running this code snippet:
for i in range(97):
s = f"{i} * 38 % 97"
print(s, "==", eval(s))
Exactly one of the lines will reveal the congruence d * 38 % 97 == 1. There are, of course, smarter ways to compute the inverse but the brute force demonstration above should make it easier to understand what a modular inverse means.
With integer arguments and mod specified, pow() does arithmetic in the "multiplicative group of integers modulo mod"
For example, the integers relatively prime to 8 (1, 3, 5, and 7) form a group under multiplication mod 8. The identity is 1. Since 3*3 = 9 is congruent to 1 modulo 8, 3 is its own inverse in this group, and
>>> pow(3, -1, 8)
3
In the doc example, 23 and 38 are inverses modulo 97.
>>> pow(23, -1, 97)
38
>>> pow(38, -1, 97)
23
This isn't particularly esoteric, but rather basic tools in number theory.
The answer from #wim and the example by #Tim Peters helps me understand what's going on in this pow() function. Let's take an example,
>>> pow(3, -1, 8)
3
Modulo by a number m must be in the range(0,m). For example 14%5 must be in range(0,5), hence it's 4.
So modulo 1/3 % 8 must be in the range(8). But as 1/3=0.33 which is not in the range, we need a way around to find it.
1/3 % 8 cannot be zero, as it's not divisible. So the lowest possible value is 1. That means, we need to represent 1/3 in such a way that x % 8 == 1 becomes True. It's obvious that 9 % 8 == 1.
As 3(target value) * 3(base) = 9, hence, the answer is 3(target value).
For a complex example, let's take:
>>> pow(38, -1, mod=97)
23
1/38=0.026. Again, need a way around. As the lowest mod should be 1, hence x % 97 == 1. Obviously 98 % 97 == 1, but 98/38 is not a whole number. Next, (2*97+1) or 195 % 97 == 1, but 195/38 is not a whole number.
In this process, (9*97+1) or 874 % 97 == 1 and 874/38=23. So the final expression becomes:
23 * 38 % 97 == 1
Hence, the answer is 23.

Finding digits in powers of 2 fast

The task is to search every power of two below 2^10000, returning the index of the first power in which a string is contained. For example if the given string to search for is "7" the program will output 15, as 2^15 is the first power to contain 7 in it.
I have approached this with a brute force attempt which times out on ~70% of test cases.
for i in range(1,9999):
if search in str(2**i):
print i
break
How would one approach this with a time limit of 5 seconds?
Try not to compute 2^i at each step.
pow = 1
for i in xrange(1,9999):
if search in str(pow):
print i
break
pow *= 2
You can compute it as you go along. This should save a lot of computation time.
Using xrange will prevent a list from being built, but that will probably not make much of a difference here.
in is probably implemented as a quadratic string search algorithm. It may (or may not, you'd have to test) be more efficient to use something like KMP for string searching.
A faster approach could be computing the numbers directly in decimal
def double(x):
carry = 0
for i, v in enumerate(x):
d = v*2 + carry
if d > 99999999:
x[i] = d - 100000000
carry = 1
else:
x[i] = d
carry = 0
if carry:
x.append(carry)
Then the search function can become
def p2find(s):
x = [1]
for y in xrange(10000):
if s in str(x[-1])+"".join(("00000000"+str(y))[-8:]
for y in x[::-1][1:]):
return y
double(x)
return None
Note also that the digits of all powers of two up to 2^10000 are just 15 millions, and searching the static data is much faster. If the program must not be restarted each time then
def p2find(s, digits = []):
if len(digits) == 0:
# This precomputation happens only ONCE
p = 1
for k in xrange(10000):
digits.append(str(p))
p *= 2
for i, v in enumerate(digits):
if s in v: return i
return None
With this approach the first check will take some time, next ones will be very very fast.
Compute every power of two and build a suffix tree using each string. This is linear time in the size of all the strings. Now, the lookups are basically linear time in the length of each lookup string.
I don't think you can beat this for computational complexity.
There are only 10000 numbers. You don't need any complex algorithms. Simply calculated them in advance and do search. This should take merely 1 or 2 seconds.
powers_of_2 = [str(1<<i) for i in range(10000)]
def search(s):
for i in range(len(powers_of_2)):
if s in powers_of_2[i]:
return i
Try this
twos = []
twoslen = []
two = 1
for i in xrange(10000):
twos.append(two)
twoslen.append(len(str(two)))
two *= 2
tens = []
ten = 1
for i in xrange(len(str(two))):
tens.append(ten)
ten *= 10
s = raw_input()
l = len(s)
n = int(s)
for i in xrange(len(twos)):
for j in xrange(twoslen[i]):
k = twos[i] / tens[j]
if k < n: continue
if (k - n) % tens[l] == 0:
print i
exit()
The idea is to precompute every power of 2, 10 and and also to precompute the number of digits for every power of 2. In this way the problem is reduces to finding the minimum i for which there exist a j such that after removing the last j digits from 2 ** i you obtain a number which ends with n or expressed as a formula (2 ** i / 10 ** j - n) % 10 ** len(str(n)) == 0.
A big problem here is that converting a binary integer to decimal notation takes time quadratic in the number of bits (at least in the straightforward way Python does it). It's actually faster to fake your own decimal arithmetic, as #6502 did in his answer.
But it's very much faster to let Python's decimal module do it - at least under Python 3.3.2 (I don't know how much C acceleration is built in to Python decimal versions before that). Here's code:
class S:
def __init__(self):
import decimal
decimal.getcontext().prec = 4000 # way more than enough for 2**10000
p2 = decimal.Decimal(1)
full = []
for i in range(10000):
s = "%s<%s>" % (p2, i)
##assert s == "%s<%s>" % (str(2**i), i)
full.append(s)
p2 *= 2
self.full = "".join(full)
def find(self, s):
import re
pat = s + "[^<>]*<(\d+)>"
m = re.search(pat, self.full)
if m:
return int(m.group(1))
else:
print(s, "not found!")
and sample usage:
>>> s = S()
>>> s.find("1")
0
>>> s.find("2")
1
>>> s.find("3")
5
>>> s.find("65")
16
>>> s.find("7")
15
>>> s.find("00000")
1491
>>> s.find("666")
157
>>> s.find("666666")
2269
>>> s.find("66666666")
66666666 not found!
s.full is a string with a bit over 15 million characters. It looks like this:
>>> print(s.full[:20], "...", s.full[-20:])
1<0>2<1>4<2>8<3>16<4 ... 52396298354688<9999>
So the string contains each power of 2, with the exponent following a power enclosed in angle brackets. The find() method constructs a regular expression to search for the desired substring, then look ahead to find the power.
Playing around with this, I'm convinced that just about any way of searching is "fast enough". It's getting the decimal representations of the large powers that sucks up the vast bulk of the time. And the decimal module solves that one.

Find the division remainder of a number

How could I go about finding the division remainder of a number in Python?
For example:
If the number is 26 and divided number is 7, then the division remainder is 5.
(since 7+7+7=21 and 26-21=5.)
For simple divisibility testing, see How do you check whether a number is divisible by another number?.
you are looking for the modulo operator:
a % b
for example:
>>> 26 % 7
5
Of course, maybe they wanted you to implement it yourself, which wouldn't be too difficult either.
The remainder of a division can be discovered using the operator %:
>>> 26%7
5
In case you need both the quotient and the modulo, there's the builtin divmod function:
>>> seconds= 137
>>> minutes, seconds= divmod(seconds, 60)
26 % 7 (you will get remainder)
26 / 7 (you will get divisor, can be float value)
26 // 7 (you will get divisor, only integer value)
If you want to get quotient and remainder in one line of code (more general usecase), use:
quotient, remainder = divmod(dividend, divisor)
#or
divmod(26, 7)
From Python 3.7, there is a new math.remainder() function:
from math import remainder
print(remainder(26,7))
Output:
-2.0 # not 5
Note, as above, it's not the same as %.
Quoting the documentation:
math.remainder(x, y)
Return the IEEE 754-style remainder of x with
respect to y. For finite x and finite nonzero y, this is the
difference x - n*y, where n is the closest integer to the exact value
of the quotient x / y. If x / y is exactly halfway between two
consecutive integers, the nearest even integer is used for n. The
remainder r = remainder(x, y) thus always satisfies abs(r) <= 0.5 *
abs(y).
Special cases follow IEEE 754: in particular, remainder(x, math.inf)
is x for any finite x, and remainder(x, 0) and remainder(math.inf, x)
raise ValueError for any non-NaN x. If the result of the remainder
operation is zero, that zero will have the same sign as x.
On platforms using IEEE 754 binary floating-point, the result of this
operation is always exactly representable: no rounding error is
introduced.
Issue29962 describes the rationale for creating the new function.
If you want to avoid modulo, you can also use a combination of the four basic operations :)
26 - (26 // 7 * 7) = 5
Use the % instead of the / when you divide. This will return the remainder for you. So in your case
26 % 7 = 5
We can solve this by using modulus operator (%)
26 % 7 = 5;
but
26 / 7 = 3 because it will give quotient but % operator will give remainder.
Modulo would be the correct answer, but if you're doing it manually this should work.
num = input("Enter a number: ")
div = input("Enter a divisor: ")
while num >= div:
num -= div
print num
You can find remainder using modulo operator
Example
a=14
b=10
print(a%b)
It will print 4
If you want the remainder of your division problem, just use the actual remainder rules, just like in mathematics. Granted this won't give you a decimal output.
valone = 8
valtwo = 3
x = valone / valtwo
r = valone - (valtwo * x)
print "Answer: %s with a remainder of %s" % (x, r)
If you want to make this in a calculator format, just substitute valone = 8
with valone = int(input("Value One")). Do the same with valtwo = 3, but different vairables obviously.
Here's an integer version of remainder in Python, which should give the same results as C's "%" operator:
def remainder(n, d):
return (-1 if n < 0 else 1) * (abs(n) % abs(d))
Expected results:
remainder(123, 10) == 3
remainder(123, -10) == 3
remainder(-123, 10) == -3
remainder(-123, -10) == -3
you can define a function and call it remainder with 2 values like rem(number1,number2) that returns number1%number2
then create a while and set it to true then print out two inputs for your function holding number 1 and 2 then print(rem(number1,number2)

Base-2 (Binary) Representation Using Python

Building on How Do You Express Binary Literals in Python, I was thinking about sensible, intuitive ways to do that Programming 101 chestnut of displaying integers in base-2 form. This is the best I came up with, but I'd like to replace it with a better algorithm, or at least one that should have screaming-fast performance.
def num_bin(N, places=8):
def bit_at_p(N, p):
''' find the bit at place p for number n '''
two_p = 1 << p # 2 ^ p, using bitshift, will have exactly one
# bit set, at place p
x = N & two_p # binary composition, will be one where *both* numbers
# have a 1 at that bit. this can only happen
# at position p. will yield two_p if N has a 1 at
# bit p
return int(x > 0)
bits = ( bit_at_p(N,x) for x in xrange(places))
return "".join( (str(x) for x in bits) )
# or, more consisely
# return "".join([str(int((N & 1 << x)>0)) for x in xrange(places)])
For best efficiency, you generally want to process more than a single bit at a time.
You can use a simple method to get a fixed width binary representation. eg.
def _bin(x, width):
return ''.join(str((x>>i)&1) for i in xrange(width-1,-1,-1))
_bin(x, 8) will now give a zero padded representation of x's lower 8 bits. This can be used to build a lookup table, allowing your converter to process 8 bits at a time (or more if you want to devote the memory to it).
_conv_table = [_bin(x,8) for x in range(256)]
Then you can use this in your real function, stripping off leading zeroes when returning it. I've also added handling for signed numbers, as without it you will get an infinite loop (Negative integers conceptually have an infinite number of set sign bits.)
def bin(x):
if x == 0:
return '0' #Special case: Don't strip leading zero if no other digits
elif x < 0:
sign='-'
x*=-1
else:
sign = ''
l=[]
while x:
l.append(_conv_table[x & 0xff])
x >>= 8
return sign + ''.join(reversed(l)).lstrip("0")
[Edit] Changed code to handle signed integers.
[Edit2] Here are some timing figures of the various solutions. bin is the function above, constantin_bin is from Constantin's answer and num_bin is the original version. Out of curiosity, I also tried a 16 bit lookup table variant of the above (bin16 below), and tried out Python3's builtin bin() function. All timings were for 100000 runs using an 01010101 bit pattern.
Num Bits: 8 16 32 64 128 256
---------------------------------------------------------------------
bin 0.544 0.586 0.744 1.942 1.854 3.357
bin16 0.542 0.494 0.592 0.773 1.150 1.886
constantin_bin 2.238 3.803 7.794 17.869 34.636 94.799
num_bin 3.712 5.693 12.086 32.566 67.523 128.565
Python3's bin 0.079 0.045 0.062 0.069 0.212 0.201
As you can see, when processing long values using large chunks really pays off, but nothing beats the low-level C code of python3's builtin (which bizarrely seems consistently faster at 256 bits than 128!). Using a 16 bit lookup table improves things, but probably isn't worth it unless you really need it, as it uses up a large chunk of memory, and can introduce a small but noticalbe startup delay to precompute the table.
Not screaming-fast, but straightforward:
>>> def bin(x):
... sign = '-' if x < 0 else ''
... x = abs(x)
... bits = []
... while x:
... x, rmost = divmod(x, 2)
... bits.append(rmost)
... return sign + ''.join(str(b) for b in reversed(bits or [0]))
It is also faster than num_bin:
>>> import timeit
>>> t_bin = timeit.Timer('bin(0xf0)', 'from __main__ import bin')
>>> print t_bin.timeit(number=100000)
4.19453350997
>>> t_num_bin = timeit.Timer('num_bin(0xf0)', 'from __main__ import num_bin')
>>> print t_num_bin.timeit(number=100000)
4.70694716882
Even more, it actually works correctly (for my definition of "correctness" :)):
>>> bin(1)
'1'
>>> num_bin(1)
'10000000'

Categories