user2699
user2699

Reputation: 3147

Using large index in python (numpy or lists)

I frequently need to enter large integers for indexing and creating numpy arrays, such as 3500000 or 250000. Normally I'd enter these using scientific notation, 3.5e6 or .25e6 or such. This is quicker, and much less likely to have errors.

Unfortunately, python expects integer datatypes for indexing. The obvious solution is to convert datatypes. So [5e5:1e6] becomes [int(5e5):int(1e6)], but this decreases readability and is somewhat longer to type. Not to mention, it's easy to forget what datatype an index is until an indexing operation fails on a list or numpy.ndarray.

Is there a way to have numpy or python interpret large floats as integers, or is there an easy way to create large integers in python?

Upvotes: 1

Views: 709

Answers (6)

naoki fujita
naoki fujita

Reputation: 719

My cheap solution is to create a helper function in proper scope.

def e(coeff, exponent):
    return int (coeff * 10 ** exponent)
np_array[e(3.5,6)] # use like this

But this cheaper answer may cause round off error, Create alias for int in proper scope is simple and clean solution.

e=int # in proper scope

Upvotes: 2

user2699
user2699

Reputation: 3147

This should fix the problems with indexing lists and arrays with floats,

slice_orig = slice
def slice(*args):
    return slice_orig(*[int(i) for i in args])

slice.__doc__ = slice_orig.__doc__+ """
WARNING: overridden to convert (stop, start, step) to integers"""

It doesn't allow using large numbers with other numpy functions requiring an int type.

EDIT: This has to be used explicitly, such as list[slice(1e5)], so it's not as useful as I expected.

Upvotes: 0

ragardner
ragardner

Reputation: 1975

You can add a shorter name to int() such as I

I = int

x = I(3.5e6)
print (x)
#3500000

This still allows use of int() normally

Upvotes: 0

Stefan Pochmann
Stefan Pochmann

Reputation: 28606

In a comment you considered having e5 = 10**5 for use as in 35*e5, lamenting it doesn't support 3.5*e6. Here's a hack that does:

class E:
    def __init__(self, e):
        self.val = 10**e
    def __rmul__(self, x):
        return int(x * self.val)

Demo:

>>> e6 = E(6)
>>> 3.5*e6
3500000

Though due to floats being lossy, this can lead to slight inaccurracies, for example:

>>> 0.1251*e6
125099

Here's a better hack, building the literal '0.1251e6' and evaluating that:

class E:
    def __init__(self, e):
        self.e = e
    def __rmul__(self, x):
        return int(float('%se%d' % (x, self.e)))

Demo:

>>> e6 = E(6)
>>> 0.1251*e6
125100

Upvotes: 2

CrazyElf
CrazyElf

Reputation: 763

I can propose to use such notation [5*10**5:1*10**6] but it's not so clear as in case of 5e5 and 1e6. And even worse in case of 3.5e6 = 35*10**5

Upvotes: 1

Stefan Pochmann
Stefan Pochmann

Reputation: 28606

If you're worried about mistakes in the number of zeros, try underscores.

>>> 3_500_000
3500000

Upvotes: 2

Related Questions