bất kỳ tài liệu nào nói chính xác phạm vi số nào là .NET BigIntegers được thiết kế cho?


12

Tôi đang chơi xung quanh với .NET BigInteger và về cơ bản tôi đang tự hỏi con số nào - một câu trả lời ước tính sẽ ổn-- là điểm sai lệch của đường cong (biểu đồ (tăng thời gian cần thiết cho các hoạt động) so với (giá trị của BigInteger))?

hoặc chúng được thiết kế không có độ lệch như vậy sao cho nếu chúng ta vẽ biểu đồ tăng thời gian cần thiết cho các hoạt động so với giá trị của BigInteger từ 1 đến vô cùng, chúng ta sẽ có một đường cong trơn tru?

ví dụ, giả sử mảng được thiết kế với khả năng xử lý 50 mục. điều này có nghĩa là nếu tôi có 1 mục, các thao tác là f (1) thời gian. và khi tôi có 2 mục, hoạt động là f (2) thời gian. nếu tôi có 50 mục, hoạt động là f (50) thời gian. nhưng vì nó được thiết kế để chỉ xử lý 50 mục, nên các thao tác được thực hiện khi chúng tôi có 51 mục sẽ là g (51) trong đó g (51)> f (51).

Nếu được thực hiện đúng, độ phức tạp của số học BigInteger sẽ là một đường cong trơn tru. Ví dụ, độ phức tạp thời gian của phép nhân phải là O (NM) trong đó N là số chữ số trong bội số thứ nhất và M là số chữ số trong bội số thứ hai. Tất nhiên, có những giới hạn thực tế ở chỗ bạn có thể chọn N và M lớn đến mức những con số không vừa với máy của bạn.

Có ai / có ai biết bất kỳ tài liệu nào tuyên bố rằng nó được thực hiện như vậy không?


3
Cử tri @Down, bỏ phiếu không có ý nghĩa gì nếu bạn không thể để lại nhận xét giải thích lý do tại sao câu hỏi không phải là một câu hỏi hay. Tôi ủng hộ điều này vì tôi thấy không có vấn đề gì với nó.
Người đàn ông Muffin

Tôi đã không downvote, nhưng tôi không chắc câu hỏi ở đây là gì. Bạn có muốn biết độ phức tạp của thời gian chạy / bộ nhớ của các hoạt động trên các phần lớn (cộng, nhân, chia, v.v.) không?
nikie

ví dụ, giả sử mảng được thiết kế với khả năng xử lý 50 mục. điều này có nghĩa là nếu tôi có 1 mục và các thao tác là f (1) thời gian. và khi tôi có 2 mục, hoạt động là f (2) thời gian. nếu tôi có 50 mục hoạt động là f (50) thời gian. nhưng vì nó được thiết kế để chỉ xử lý 50 mục, nên các thao tác được thực hiện khi chúng tôi có 51 mục sẽ là g (51) trong đó g (51)> f (51)
Pacerier

@ Charles E. Cấp có! đây là những gì tôi đang nói câu hỏi là có bất kỳ / có ai biết bất kỳ tài liệu nào tuyên bố rằng nó được thực hiện như vậy không?
Pacerier

@Paceier Tôi đã chuyển nhận xét của mình vào câu trả lời của mình và thêm một liên kết đến một tài liệu thảo luận chính xác về điều này.
Charles E. Grant

Câu trả lời:


7

Bất kỳ số nào có thể có thể lớn hơn ULong.MaxValue hoặc nhỏ hơn Long.MinValue nên được biểu diễn bằng BigInteger.

Nếu KHÔNG (Long.MinValue <= X <= ULong.MaxValue) thì BigInteger

BigInteger dành cho số lượng quá lớn so với người nguyên thủy bình thường có thể xử lý.

Ví dụ: nếu số nguyên của bạn nằm ngoài phạm vi của Long, có lẽ bạn nên sử dụng BigInteger. Tuy nhiên, những trường hợp này rất hiếm và sử dụng các lớp này có chi phí cao hơn đáng kể so với các đối tác nguyên thủy của chúng.

Ví dụ: longrộng 64 bit và có thể giữ phạm vi: -9,223,372,036,854,775,809 đến 9,223,372,036,854,775,80. ulong có thể giữ 0 đến 18,446,744,073,709,551,615. Nếu số của bạn lớn hơn hoặc nhỏ hơn số đó, BigInteger là lựa chọn duy nhất của bạn

Lần duy nhất tôi thấy chúng được sử dụng trong một ứng dụng trong thế giới thực là một ứng dụng tinh bột.

Xem thêm: Phạm vi nguyên thủy trong .NET


ý tôi là tất nhiên tôi biết chúng ta nên sử dụng các nguyên thủy bình thường bất cứ khi nào chúng ta có thể .. ý tôi muốn nói là BigInteger được thiết kế cho các số lớn hơn 100 lần so với ULong.MaxValue hoặc là BigInteger được thiết kế cho các số lớn hơn 100 nghìn lần so với ULong.MaxValue? ý tôi là tôi biết nó có thể hỗ trợ lớn hơn 100 nghìn lần so với ULong.MaxValue nhưng nó được thiết kế với phạm vi này hay nó được thiết kế với phạm vi này được tuyên bố là "yêu cầu khác thường"?
Pacerier

5
Bạn không thể đại diện cho một số thậm chí một số lớn hơn ULong.MaxValue mà không sử dụng BigInteger, vì vậy đó là cho điều đó. Bất kỳ số nào có thể có thể lớn hơn ULong.MaxValue phải là BigInteger.
Malfist

tất nhiên có nhiều cách để biểu diễn các số lớn hơn ULong.MaxValue và không sử dụng BigInteger. tôi chỉ đơn giản có thể viết một cấu trúc tùy chỉnh bao gồm một ULong và boolean và viola tôi có thể đại diện cho hai lần của ULong.MaxValue
Pacerier

Đúng, nhưng việc sử dụng BigInteger sẽ ít phức tạp hơn và có lẽ nó sẽ nhanh hơn nhiều, nếu nhanh hơn và nó sẽ không linh hoạt như BigInteger. Bạn cũng có thể đại diện cho số lượng rất lớn với một loạt các booleans, nhưng điều đó quá phức tạp.
Malfist

2
@Mavrik, anh ấy đã thay đổi câu hỏi này thành một câu hỏi hoàn toàn khác so với câu hỏi tôi đã trả lời.
Malfist

4

Trong một số trường hợp, điểm của BigInteger không có kích thước tuyệt đối vì nó có độ chính xác không giới hạn. Số dấu phẩy động cũng có thể rất lớn, nhưng có độ chính xác hạn chế. BigInteger cho phép bạn thực hiện số học mà không cần lo lắng về lỗi làm tròn hoặc tràn. Cái giá bạn phải trả là chậm hơn hàng trăm lần so với số học với số nguyên thông thường hoặc số dấu phẩy động.

Như những người khác đã chỉ ra, ulong có thể giữ từ 0 đến 18,446,744,073,709,551,615 và miễn là bạn ở trong phạm vi đó, bạn có thể thực hiện số học chính xác. Nếu bạn vượt quá 1 phạm vi đó, bạn sẽ bị tràn, vì vậy câu trả lời cho câu hỏi của bạn là sử dụng BigInteger nếu bạn cần số học chính xác và có bất kỳ kết quả trung gian nào sẽ vượt quá 18.446.744.073.709.551.615.

Hầu hết các vấn đề về khoa học, kỹ thuật và tài chính có thể sống với các xấp xỉ bị ép buộc bởi các số dấu phẩy động và không thể chi trả chi phí thời gian của số học BigInteger. Hầu hết các tính toán thương mại không thể sống với các xấp xỉ của số học dấu phẩy động, nhưng hoạt động trong phạm vi 0 đến 18,446,744,073,709,551,615, vì vậy chúng có thể sử dụng số học thông thường. BigInteger là cần thiết khi sử dụng các thuật toán từ lý thuyết số bao gồm những thứ như mật mã học (nghĩ số nguyên tố 50 chữ số). Đôi khi nó cũng được sử dụng trong các ứng dụng thương mại khi cần tính toán chính xác, tốc độ không quá quan trọng và việc thiết lập một hệ thống dấu thập phân cố định thích hợp là quá nhiều rắc rối.

Nếu được thực hiện đúng, độ phức tạp của số học BigInteger sẽ là một đường cong trơn tru. Ví dụ, độ phức tạp thời gian của phép nhân phải là O (NM) trong đó N là số chữ số trong bội số thứ nhất và M là số chữ số trong bội số thứ hai. Tất nhiên, có những giới hạn thực tế ở chỗ bạn có thể chọn N và M lớn đến mức những con số không vừa với máy của bạn.

Nếu bạn google "Độ phức tạp tính toán của biginteger", bạn sẽ nhận được nhiều tài liệu tham khảo hơn mức bạn có thể lắc. Một câu nói trực tiếp cho câu hỏi của bạn là: So sánh hai gói số học chính xác tùy ý .


4

Giới hạn bộ nhớ

BigInteger dựa vào mảng int để lưu trữ. Giả sử điều này, giới hạn lý thuyết cho số lượng tối đa, mà BigInteger có khả năng đại diện, có thể được lấy từ kích thước mảng tối đa có sẵn trong .net. Có một chủ đề SO về mảng ở đây: Tìm kiếm bao nhiêu bộ nhớ tôi có thể phân bổ cho một mảng trong C # .

Giả sử rằng chúng ta biết kích thước mảng tối đa, chúng ta có thể ước tính số lượng tối đa, mà BigInteger có thể đại diện: (2 ^ 32) ^ max_array_size, trong đó:

  • 2 ^ 32 - số lượng tối đa trong ô mảng (int)
  • max_array_size - kích thước tối đa cho phép của mảng int bị giới hạn bởi kích thước đối tượng là 2GB

Điều này cho số với 600 triệu chữ số thập phân.

Giới hạn hiệu suất

Về hiệu suất, BigInteger sử dụng thuật toán Karatsuba để nhân và thuật toán tuyến tính để thêm. Độ phức tạp nhân là 3 * n ^ 1.585, điều đó có nghĩa là nó sẽ mở rộng khá tốt ngay cả đối với số lượng lớn ( Đồ thị độ phức tạp ), tuy nhiên bạn vẫn có thể đạt được hiệu suất phạt tùy thuộc vào kích thước của RAM và bộ đệm của bộ xử lý.

Cho đến nay, khi kích thước số tối đa được giới hạn ở mức 2GB, trên máy gốc bạn sẽ không thấy khoảng cách hiệu suất bất ngờ, nhưng vẫn hoạt động trên 600 triệu chữ số sẽ bị chậm.


đây là thông tin tuyệt vời, tuy nhiên nguồn của bạn mà BigInteger dựa vào mảng int ở đâu?
Pacerier

Tôi vừa tìm hiểu các nguồn .net bằng dotPeek. Có vẻ như chính số đó được lưu trữ bên trong uint [] _data của cấu trúc BigInteger.
Valera Kolupaev

* Được cập nhật với câu trả lời chi tiết hơn, tuy nhiên, tôi không thể tìm thấy bất kỳ mã nguồn .net nào mà tôi có thể tham khảo, ngoại trừ các đoạn được dịch ngược.
Valera Kolupaev

Dường như với tôi có một thuật toán nhân nổi bật trong .NET vì nó có thể được tìm ra từ ILSpy: .NET BigInteger Multiplication
Ivan Kochurkin 16/214

1

Giới hạn là kích thước bộ nhớ của bạn (và thời gian bạn có). Vì vậy, bạn có thể có những con số thực sự lớn. Như Kevin đã nói, trong mật mã học, người ta phải nhân hoặc nhân số mũ với một vài nghìn chữ số (nhị phân), và điều này là có thể mà không gặp vấn đề gì.

Tất nhiên, thường thì các thuật toán trở nên chậm hơn khi các con số trở nên lớn hơn, nhưng không quá chậm.

Tuy nhiên, khi bạn đang sử dụng các số trong phạm vi chữ số lớn, bạn có thể muốn nghĩ về các giải pháp khác - vì thực sự tính toán với chúng cũng bị chậm.


0

Có một vài ứng dụng trong cộng đồng khoa học (tức là khoảng cách giữa các thiên hà, số lượng nguyên tử trên một cánh đồng cỏ, v.v.)


uh đừng thô lỗ .. nhưng câu trả lời này liên quan đến câu hỏi như thế nào?
Pacerier

2
Câu hỏi, như được viết, nghe có vẻ như anh ta đang tìm kiếm ví dụ trong thế giới thực về lý do tại sao loại dữ liệu đó sẽ cần phải được tạo ra.
Dave Wise

một cụm từ tốt hơn sẽ là "BigInteger có thực sự phù hợp với số lượng lớn như 10 ^ 30" không?
Pacerier

Đối với điều này, tôi sẽ sử dụng tốt hơn doublehoặc float- bạn không có độ chính xác cần thiết.
Paŭlo Ebermann

một cụm từ tốt hơn sẽ là "BigInteger có thực sự phù hợp với các số lớn tới 10 ^ 30 khi chúng ta cần độ chính xác không"?
Pacerier

0

Như câu trả lời của kevin cline cho thấy, BigNumbers đã được thêm vào thư viện .NET một cách thô sơ vì chúng cần thiết như một khối xây dựng cho nhiều thuật toán mã hóa hiện đại (chữ ký số, mã hóa khóa công khai / riêng tư, v.v.). Nhiều thuật toán mã hóa hiện đại liên quan đến các tính toán trên các giá trị nguyên với kích thước lên tới vài nghìn bit. Vì lớp BigNumber mô tả một lớp hữu ích và được xác định rõ ràng, họ đã quyết định công khai nó (thay vì giữ nó như một chi tiết nội bộ của API mã hóa).


btw chỉ tò mò nguồn của bạn mà BigNumbers đã được thêm vào thư viện .NET chủ yếu là vì chúng cần thiết như một khối xây dựng cho nhiều thuật toán mã hóa hiện đại (và do đó có thể hỗ trợ các giá trị lên đến vài nghìn bit)?
Pacerier
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.