2012-01-23 108 views
5

Tôi đang làm một câu đố, nơi tôi phải đối phó với số thứ tự 10^18. Tuy nhiên, tôi thấy python không thể xử lý số lượng rất lớn trong tất cả các lĩnh vực.Tại sao python không xử lý số lượng rất lớn trong tất cả các lĩnh vực?

Cụ thể, nếu chúng tôi gán một = 1000000000000000000 (10^18) và thực hiện các phép tính số học cơ bản (+, -, /, *), đáp ứng của nó. Tuy nhiên, nó hiển thị OverflowError khi tôi sử dụng nó trong phạm vi()

>>> a = 1000000000000000000 
>>> a/2 
500000000000000000L 
>>> a*2 
2000000000000000000L 
>>> a+a 
2000000000000000000L 
>>> a*a 
1000000000000000000000000000000000000L 
>>> range(a) 

Traceback (most recent call last): 
    File "<pyshell#5>", line 1, in <module> 
    range(a) 
OverflowError: range() result has too many items 
>>> xrange(a) 

Traceback (most recent call last): 
    File "<pyshell#6>", line 1, in <module> 
    xrange(a) 
OverflowError: Python int too large to convert to C long 

Tôi đã sử dụng Python 2.7.

  1. Làm cách nào để xử lý các câu đố như vậy. (Một tài liệu tham khảo hướng dẫn/cuốn sách sẽ được đánh giá)
  2. Tại sao Python không có khả năng xử lý nó trong phạm vi()/xrange()

Tôi muốn làm điều đó trong python 2.7 sử dụng chức năng inbuild. Không phải là có thể?

+2

Có thể trùng lặp http://stackoverflow.com/questions/1482480/xrange2100-overflowerror-long-int-too-large-to-convert-to-int –

+2

Tôi nghi ngờ bạn sẽ giải quyết câu đố của mình đúng cách . Đếm đến 10^18 với python trên một máy tính của ngày hôm nay sẽ mất một nơi nào đó theo thứ tự 10000 năm. –

+0

itertools.count() có vẻ là một lựa chọn cho nó, nhưng việc đếm là mất nhiều thời gian. Có bất kỳ lựa chọn hiệu quả nào khác không (xem xét các tình huống mà chúng ta cần đếm các giá trị lớn; giải quyết các câu đố) – Surya

Trả lời

10

Trong Python 2.x, rangexrange bị giới hạn khi làm việc với C long và các số nguyên lớn của bạn quá lớn. Giới hạn này chỉ đơn giản là do các lựa chọn thực hiện được thực hiện cho rangexrange.

Trong Python 3.x giới hạn đã bị xóa và bạn có thể thực hiện range() với các số nguyên rất lớn.

>>> range(2**128) 
range(0, 340282366920938463463374607431768211456) 

Các official list of changes for Python 3 có này để nói:

range() nay hoạt động như xrange() sử dụng để cư xử, ngoại trừ nó hoạt động với các giá trị của kích thước tùy ý. Cái sau không còn tồn tại nữa.


Trong Python 2.x các range() chức năng quay trở lại một danh sách. Rõ ràng không có hy vọng phân bổ bộ nhớ cho tất cả các yếu tố cho phạm vi rất lớn. Hàm xrange() trả về đối tượng xrange. Các documentation mô tả nó là "một loại chuỗi đục mà sản lượng các giá trị tương tự như danh sách tương ứng, mà không thực sự lưu trữ tất cả cùng một lúc". Tài liệu này tiếp tục để nói điều này:

xrange() được thiết kế đơn giản và nhanh chóng. Việc triển khai có thể áp đặt các hạn chế để đạt được điều này. Việc triển khai C của Python hạn chế tất cả các đối số đối với các độ dài C nguyên gốc (các số nguyên Python "ngắn"), và cũng yêu cầu số lượng các phần tử phù hợp trong một C bản địa dài.

Điều này giải thích những hạn chế trong Python 2.x.


Tôi không chắc bạn có thể làm gì với hỗ trợ Python 3 mới cho các phạm vi rất lớn. Ví dụ: Tôi sẽ không khuyên bạn nên thử cách này:

2**128 in range(2**128) 

Điều đó sẽ chạy trong một thời gian dài.


Bạn cho biết trong nhận xét rằng bạn đang viết mã để đếm đến số lượng lớn. Bạn có thể làm điều này trivially bằng Python với mã như thế này:

i = 0 
while i<N: 
    doSomething(i) 
    i += 1 

Nhưng bạn sẽ khám phá ra rằng nếu N là một số lượng lớn thì điều này sẽ mất một thời gian rất dài. Không có bất kỳ xung quanh nào cho các giá trị của N của đơn đặt hàng 2 theo câu hỏi của bạn.

+0

Tôi nghĩ rằng tôi nên tìm một cách khác cho các giải pháp như đạt N thường là không thể. – Surya

+0

Đúng vậy. Bạn không thể mong đợi để đếm đến 2^18. –

+2

Nhỏ: trong Python 3 hiện đại, '2 ** 128 trong phạm vi (2 ** 128)' sẽ chạy ngay lập tức vì '__contains__' đã được đặt biệt. – DSM

1

Vấn đề của bạn là phạm vi() trong Python 2.7 xây dựng danh sách rõ ràng của mọi giá trị trong phạm vi - bạn chỉ đơn giản là không có đủ tài nguyên để tạo danh sách như vậy.

Python 3 sửa hành vi này - và chỉ tính giá trị theo yêu cầu ... như thể bằng biểu thức trình tạo. Chức năng Python 2 xrange() sẽ không giúp bạn vì nó bị ràng buộc để đăng ký giá trị ... đó là một sự thỏa hiệp cho Python 2 để tránh chi phí khổng lồ của phạm vi() đối với bất kỳ số nào không phải là tầm thường nhỏ.

Một cách tiếp cận có thể là để xác định máy phát điện riêng của bạn mà lặp qua các số nguyên tùy ý - một cái gì đó như:

def genrange(min,max,stride=1): 
    val=min 
    while val<max: 
     yield val 
     val+=stride 

nghi ngờ của tôi, tuy nhiên, là điều này có lẽ là một sai lầm trong kế hoạch lớn hơn của sự vật - như bạn 'không có đủ tài nguyên xử lý để lặp qua mọi giá trị trong một số nguyên 32 bit - hãy để một mình cho phạm vi số nguyên lớn hơn giá trị của một thanh ghi (32bit). Tôi nghi ngờ có một cách tốt hơn để giải quyết vấn đề của bạn mà không phụ thuộc vào một phạm vi ở nơi đầu tiên.

+0

Đây có thể là một cách (có thể không hiệu quả) để có một hàm như range(). Tuy nhiên, tôi có thể có ngay lập tức được sử dụng trong khi() thay vì đặt nó trong một chức năng. Tôi nghĩ rằng nó thậm chí sẽ làm giảm thời gian phức tạp. (Không chắc) – Surya

Các vấn đề liên quan