簡體   English   中英

存儲大量基數B的最佳方法是什么?

[英]Best way to store large base B numbers?

存儲大型基本B編號的最佳方法是什么,以便能夠有效地完成右移和檢查最低有效位等操作?

實際上,我遇到了一個面試問題

Given two numbers N and K such that 0<=N<=1000 and 0<=K<=1000^1000. I need 
to check that whether N^N = K or not. For example:

if N=2 and K=4 , 2^2 = 4 so return true;
if N=3 and K=26 , 3^3 != 26 so return false

我在想的是,如果我考慮base N number system ,那么N^N將等於1 followed by N zero 例如 - 對於N = 2,2 ^ 2 = 100(在基數2中),對於N = 3,3 ^ 3 = 1000(在基數3中)。 然后,我可以輕松編寫一個函數來判斷K = N^N是否。

int check(unsigned long int N, unsigned long int K) 
{
    unsigned long int i;
    for (i=0; i<N; i++) 
    {
        if (K%N != 0) //checking whether LSB is 0 or not in base N number system 
           return 0;
        K = K/N; //right shift K by one. 
    }
    return (K==1);
}

現在這個功能有兩個主要問題:

1) An unsigned long int is not sufficient to store large numbers of range 0 
to 1000^1000.
2) The modulus and the division operations makes it every less efficient.  

為了使其高效,我正在尋找一些方法來表示大的基數N數,以便我可以執行右移並有效地檢查最低有效位操作。 以前有人遇到過這樣的事嗎? 或者有誰知道有效解決這個問題的任何其他方法?

要檢查相等性,您實際上不必進行高精度算術 - 您可以使用http://en.wikipedia.org/wiki/Chinese_remainder_theorem 找到足夠的質數以確保它們的乘積大於N ^ N,然后依次檢查N ^ N對K的每個質數的模數。

在實踐中,我可能會使用Java BigInteger包進行簡單的計算。

根據面試官的不同,可以接受一些答案。 如果其中任何一項都不被接受,那么希望面試官能夠迅速推動您提出其他建議。

  • 使用gmp ,或者使用mpz_t而不是unsigned long來執行除法和模數,或者只計算N^N並將其與K進行比較。 這是最簡單的方法。
  • 編寫自己的大數字庫,可能使用基數10作為內部表示而不是基數2,如果輸入在基數10中,並且認為堅持使用它可能比首先轉換為二進制更快。 當然它不一定是一個完整的算術庫,你真正需要的只是與余數的划分。
  • 發明一些你可以在開始之前做的快速測試,以避免在某些方面KN^N附近時很多工作。 例如,測試log(K) / N是否近似等於log(N) ,在任何基數中采用的日志對於輸入最方便。 或測試多少次KN是整除的數字方便像210 :如果K是不能分開的正是N次很多次N ,那么它顯然是錯誤的。 或者測試它們是否等於一些小數,例如ULONG_MAX1000000 不幸的是,這種事情只能加速某些不平等的情況,它會減慢其他一切,包括它們的情況。 所以它可能適得其反,取決於你期望的輸入。

mcdowella的回答可能是也可能不是最好的,我不知道。 特別有希望的是,您只需要生成一次素數(當您編寫程序時),並且在100 N <= 1000從1009開始的1000個素數就足夠了。 較大的素數意味着需要的更少,因此工作量更少,特別是如果它們不超過ULONG_MAX平方根。 通過平方或等效使用取冪來得到N^N模數每個素數,並且對於K ,無論輸入是什么基礎,每次都做幾個數字。

要真正閃存,對於每個預先選擇的素數p您可以編寫(或讓編譯器為您編寫)模運算操作,該操作比適用於任何除數的一般整數模運算更快。 也就是說,一個體面的編譯器i % 1009可能會快於i % j其中的價值j是在編譯時未知,但原來在運行時是1009。但要注意,在速度上的差異可能收不回(比如)通過函數指針調用它的成本。 因此,利用它可能需要一些丑陋的重復代碼。

為什么要將數字轉換為基數N?

你可以繼續除以N.如果你在N之后得到1這樣的除數那么它就是N ^ N. 否則它不是。

您必須將K存儲為字符串並執行divison操作。

divide(k,n):
  c = ''
  a = ''
  for i in k:
    c = c+i
    a = a+ str(int(c)/ int(n))
    c = str(int(c) % int(n))
 return a

這是在python中,你可以在C中實現類似的東西

給定兩個數字N和K,使得0 <= N <= 1000且0 <= K <= 1000 ^ 1000。 我需要檢查是否N ^ N = K.

很大程度上取決於提供給代碼時這些數字的存儲方式。 假設它們是文本格式,我只是保持這種方式,並創建一個包含N ^ N值的1001個字符串數組。 您可以使用任意精度算術命令行程序(如bc來一次性創建這些字符串,並在循環中調用它。

由於1000 ^ 1000中只有1000個“好”值(並且它們將彼此相距很遠),因此可以先使用一些對數近似來猜測N. 在那之后,您最多只需要一次精確檢查(例如,使用一些bignum庫)。

這個對數不必是精確的,即使strlen()可以足夠近似。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM