.NET BigIntegers tam olarak hangi sayı aralığı için tasarlandığını belirten herhangi bir belge?


12

Ben .NET BigInteger ile oynuyorum ve temelde merak ediyorum hangi sayı - tahmini bir cevap iyi olurdu - eğrisinin sapma noktası (grafik (operasyonlar için gerekli zaman artışı) vs (BigInteger değeri))?

ya da böyle bir sapma olmadan tasarlanıyorlar, böylece BigInteger'in operasyonlar için gereken süreyi 1'den sonsuza kadar artarsak, düzgün bir eğriye sahip oluruz?

örneğin, dizilerin 50 öğeyi taşıyabilecek şekilde tasarlandığı varsayılarak. Bu, 1 öğem varsa, işlemlerin f (1) zamanı olduğu anlamına gelir. ve 2 öğem olduğunda işlemler f (2) süresidir. 50 ürünüm varsa, işlemler f (50) zamandır. ancak yalnızca 50 öğeyi işlemek için tasarlandığından, 51 öğemiz olduğunda yapılan işlemler g (51) olacaktır; burada g (51)> f (51).

Düzgün uygulanırsa, BigInteger aritmetiğinin karmaşıklığı düzgün bir eğri olmalıdır. Örneğin, çarpmanın zaman karmaşıklığı O (NM) olmalıdır, burada N, birinci çarpmadaki basamak sayısıdır ve M, ikinci çarpmadaki basamak sayısıdır. Tabii ki, N ve M'yi sayıların makinenize sığmayacağı kadar büyük seçebilmeniz için pratik sınırlar var.

Bunun uygulandığını iddia eden herhangi bir belge var mı / bilen var mı?


3
@ Düşman seçmenler, aşağı oylar, sorunun neden iyi bir soru olmadığını açıklayan bir yorum bırakamazsanız hiçbir şey ifade etmez. Bununla ilgili hiçbir sorun görmediğim için bunu iptal ettim.
Muffin Man

Ben inmedim, ama burada sorunun ne olduğundan emin değilim. Bigints'deki işlemlerin çalışma zamanı / bellek karmaşıklığını (toplama, çarpma, bölme vb.) Bilmek ister misiniz?
nikie

örneğin, dizilerin 50 öğeyi taşıyabilecek şekilde tasarlandığı varsayılarak. Bu, 1 öğem varsa ve işlemlerin f (1) zamanı olduğu anlamına gelir. ve 2 öğem olduğunda, işlemler f (2) süresidir. 50 ürünüm varsa işlemler f (50) saattir. ancak yalnızca 50 öğeyi işlemek için tasarlandığından, 51
öğemiz

@Charles E. Grant evet! bahsettiğim budur. soru var mı / böyle uygulandığını iddia eden herhangi bir belge bilen var mı?
Pacerier

@Paceier Yorumumu yanıtıma taşıdım ve tam olarak bunu tartışan bir belgeye bağlantı ekledim.
Charles E. Grant

Yanıtlar:


7

ULong.MaxValue değerinden daha büyük veya Long.MinValue değerinden daha küçük olabilecek herhangi bir sayı BigInteger kullanılarak temsil edilmelidir.

DEĞİLSE (Uzun.MinValue <= X <= ULong.MaxValue) Sonra BigInteger

BigInteger normal ilkellerin işleyebileceğinden çok daha büyük sayılar içindir.

Örneğin, tamsayınız Long aralığının dışındaysa, büyük olasılıkla BigInteger kullanmalısınız. Bu vakalar çok nadirdir ve bu sınıfların kullanılması, ilkel muadillerinden önemli ölçüde daha yüksek ek yüke sahiptir.

Örneğin long, 64 bit genişliğindedir ve aralığı tutabilir: -9,223,372,036,854,775,808 ila 9,223,372,036,854,775,80. ulong 0 ila 18,446,744,073,709,551,615 alabilir. Sayılarınız bundan büyük veya küçükse, BigInteger tek seçeneğinizdir

Onları gerçek dünya uygulamasında kullandığım tek zaman bir yıldız çizelgesi uygulamasıydı.

Ayrıca Bakınız: .NET'teki İlkel Aralıklar


i demek istediğim her zaman normal ilkeleri kullanmamız gerektiğini biliyorum .. demek istediğim BigInteger ULong.MaxValue'dan 100 kat daha büyük sayılar için tasarlanmış ya da BigInteger ULong.MaxValue'dan 100k kat daha büyük sayılar için tasarlanmış mı? yani ULong.MaxValue 100k kat daha büyük destekleyebilir biliyorum ama bu aralık göz önünde bulundurularak tasarlanmış, ya da "sıra dışı gereksinimi" ilan bu aralık ile tasarlanmış?
Pacerier

5
BigInteger kullanmadan ULong.MaxValue'dan daha büyük bir sayıyı temsil edemezsiniz, bu yüzden bunun için. ULong.MaxValue değerinden daha büyük olabilecek herhangi bir sayı bir BigInteger olmalıdır.
Malfist

elbette ULong.MaxValue değerinden büyük ve BigInteger kullanmadan sayıları temsil etmenin yolları vardır. i basitçe i ULong.MaxValue iki katı kadar temsil edebilir bir Ulong bir mantıksal ve viyola oluşan özel bir yapıya yazabilirim
Pacerier

Evet, ancak BigInteger'i kullanmak çok daha az karmaşıktır ve muhtemelen daha hızlıysa daha hızlı olmaz ve BigInteger kadar esnek olmaz. Bir dizi boolean ile çok büyük sayıları da temsil edebilirsiniz, ancak bu çok karmaşık.
Malfist

2
@Mavrik, bunu cevapladığım sorudan tamamen farklı bir soru olarak değiştirdi.
Malfist

4

Bir anlamda BigInteger'in noktası, sınırsız hassasiyet olduğu kadar mutlak boyut değildir. Kayan nokta sayıları da çok büyük olabilir, ancak hassasiyeti sınırlıdır. BigInteger, yuvarlama hataları veya taşma konusunda endişe duymadan aritmetik gerçekleştirmenizi sağlar. Ödediğiniz fiyat, sıradan tamsayılarla veya kayan nokta sayılarıyla aritmetikten yüzlerce kez daha yavaş olmasıdır.

Diğerlerinin işaret ettiği gibi, ulong 0 ila 18,446,744,073,709,551,615 arasında kalabilir ve bu aralıkta kaldığınız sürece kesin aritmetik yapabilirsiniz. Bu aralığın 1'i bile geçerseniz bir taşma elde edersiniz, bu nedenle tam aritmetiğe ihtiyacınız varsa sorunuzun cevabı BigInteger kullanmaktır ve herhangi bir ara sonucun 18,446,744,073,709,551,615'i aşma olasılığı vardır.

Bilim, mühendislik ve finanstaki çoğu sorun kayan nokta sayılarının zorladığı yaklaşımlarla yaşayabilir ve BigInteger aritmetiğinin zaman maliyetini karşılayamaz. Çoğu ticari hesaplama, kayan nokta aritmetiği yaklaşımlarıyla yaşayamaz, ancak 0 ila 18,446,744,073,709,551,615 aralığında çalışır, bu nedenle normal aritmetik kullanabilirler. BigInteger, kriptografi gibi şeyleri içeren sayı teorisinden algoritmalar kullanırken gereklidir (50 basamaklı asal sayıları düşünün). Bazen kesin hesaplamalara ihtiyaç duyulduğunda, hız çok önemli olmadığında ve uygun bir sabit ondalık nokta sisteminin kurulması çok sorun olduğunda ticari uygulamalarda da kullanılır.

Düzgün uygulanırsa, BigInteger aritmetiğinin karmaşıklığı düzgün bir eğri olmalıdır. Örneğin, çarpmanın zaman karmaşıklığı O (NM) olmalıdır, burada N, birinci çarpmadaki basamak sayısıdır ve M, ikinci çarpmadaki basamak sayısıdır. Tabii ki, N ve M'yi o kadar büyük seçebilmeniz için pratik sınırlar var ki, sayılar makinenize sığmayacak.

Eğer "biginteger'in hesaplamalı karmaşıklığı" google'da bir sopa sallamak daha fazla referans alırsınız. Sorunuza doğrudan konuşan bir tanesi şudur: İki keyfi hassas aritmetik paketin karşılaştırılması .


4

Bellek Sınırı

BigInteger, depolama için int dizisine dayanır. Bu varsayıldığında, BigInteger'ın temsil edebileceği maksimum sayı için teorik sınır, .net'te bulunan maksimum dizi boyutundan türetilebilir. Burada diziler hakkında bir SO konu var: C # bir dizi için ne kadar bellek ayırabilirim .

Maksimum dizi boyutunu bildiğimizi varsayarsak, BigInteger'in temsil edebileceği maksimum sayıyı tahmin edebiliriz: (2 ^ 32) ^ max_array_size, burada:

  • 2 ^ 32 - dizi hücresindeki maksimum sayı (int)
  • max_array_size - int dizisinin izin verilen maksimum boyutu 2 GB olan nesne boyutu ile sınırlıdır

Bu 600 milyon ondalık basamaklı bir sayı verir.

Performans Sınırı

Performansa gelince, BigInteger çarpma için Karatsuba algoritmasını ve ekleme için doğrusal algoritmayı kullanır . Çarpma karmaşıklığı, 3 * n ^ 1.585büyük sayılar için bile oldukça iyi ölçekleneceği anlamına gelir ( Karmaşıklık grafiği ), ancak RAM ve işlemci önbelleğinin boyutuna bağlı olarak yine de performans cezasına çarpabilirsiniz.

Şimdiye kadar, maksimum sayı boyutu 2GB ile sınırlı olduğundan, iniş makinesinde beklenmedik performans boşluğu görmeyeceksiniz, ancak yine de 600 milyon haneli sayılarda çalışma yavaş olacak.


bu harika bir bilgidir, ancak BigInteger'in int dizilerine dayandığı kaynağınız nerede?
Pacerier

Ben sadece dotPeek kullanarak .net kaynaklarına kazdık. Sayının kendisi BigInteger yapısının uint [] _data'sında saklanıyor gibi görünüyor.
Valera Kolupaev

* Daha ayrıntılı bir cevapla güncellendi, ancak, decompiled snippet'ler hariç, başvurabileceğim herhangi bir .net kaynak kodu bulamıyorum.
Valera Kolupaev

Bana öyle geliyor ki, ILSpy'dan anlaşılabileceği gibi .NET'te standart bir çarpma algoritması var: .NET BigInteger Multiplication
Ivan Kochurkin

1

Sınır, bellek boyutunuzdur (ve sahip olduğunuz süredir). Yani, gerçekten büyük rakamlara sahip olabilirsiniz. Kevin'in dediği gibi, kriptografide, sayıları birkaç bin (ikili) basamakla çarpmak veya üstelemek zorundadır ve bu herhangi bir sorun olmadan mümkündür.

Tabii ki, sayılar büyüdükçe algoritmalar yavaşlar, ancak çok yavaş olmaz.

Mega haneli aralıktaki sayıları kullanırken, diğer çözümler hakkında düşünmek isteyebilirsiniz - gerçekten onlarla hesaplamak da yavaşlar.


0

Bilim camiasında birkaç kullanım alanı vardır (yani galaksiler arasındaki mesafe, çim alanındaki atom sayısı, vb.)


ah kaba olmamak .. ama bu cevap soru ile nasıl ilişkilidir?
Pacerier

2
Yazıldığı gibi, bu tür veri türlerinin neden oluşturulması gerektiğine dair gerçek dünya örneği aradığı anlaşılıyor.
Dave Wise

daha iyi bir yeniden ifade "BigInteger 10 ^ 30 kadar büyük sayılar için gerçekten uygun mu?"
Pacerier

Bunun için daha iyi kullanırdım doubleveya float- zaten gerekli hassasiyete sahip değilsiniz.
Paŭlo Ebermann

daha iyi bir yeniden ifade "hassasiyete ihtiyaç duyduğumuzda 10 ^ 30 kadar büyük sayılar için gerçekten uygun mu?"
Pacerier

0

Kevin Cline'ın cevabının da belirttiği gibi, BigNumbers .NET kütüphanelerine öncelikli olarak eklendi, çünkü birçok modern şifreleme algoritması (dijital imzalar, genel / özel anahtar şifrelemesi, vb.) İçin bir yapı taşı olarak ihtiyaç duyuldular. Birçok modern şifreleme algoritması, birkaç bite kadar büyüklükteki tamsayı değerleri üzerinde hesaplamalar içerir. BigNumber sınıfı iyi tanımlanmış ve kullanışlı bir sınıf tanımladığından, onu herkese açık hale getirmeye karar verdiler (onu şifreleme API'lerinin dahili bir ayrıntısı olarak tutmak yerine).


btw sadece BigNumbers'ın öncelikle birçok modern şifreleme algoritması için bir yapı taşı olarak ihtiyaç duyuldukları için .NET kitaplıklarına eklendiğini merak ediyor (ve bu nedenle birkaç bite kadar değerleri destekleyebilmelidir)?
Pacerier
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.