快速手动修改数字的方法

时间:2009-06-12 17:32:13

标签: c# algorithm modulo

我需要能够为a和b的非常大的值计算(a ^ b)%c(它们分别是推送限制,当你尝试计算a ^ b时会导致溢出错误)。对于足够小的数字,使用标识(a ^ b)%c =(a%c)^ b%c可以工作,但如果c太大,这实际上没有帮助。我写了一个循环来手动执行mod操作,一次一个:

private static long no_Overflow_Mod(ulong num_base, ulong num_exponent, ulong mod) 
    {
        long answer = 1;
        for (int x = 0; x < num_exponent; x++)
        {
            answer = (answer * num_base) % mod;
        }
        return answer;
    }

但这需要很长时间。是否有任何简单快速的方法来执行此操作,而不必实际使用b AND的功能而不使用耗时的循环?如果所有其他方法都失败了,我可以创建一个bool数组来表示一个巨大的数据类型,并找出如何使用按位运算符来实现这一点,但必须有更好的方法。

11 个答案:

答案 0 :(得分:9)

我猜您正在寻找:http://en.wikipedia.org/wiki/Montgomery_reduction 或者基于Modular Exponentiation的简单方法(来自维基百科)

Bignum modpow(Bignum base, Bignum exponent, Bignum modulus) {

    Bignum result = 1;

    while (exponent > 0) {
        if ((exponent & 1) == 1) {
            // multiply in this bit's contribution while using modulus to keep result small
            result = (result * base) % modulus;
        }
        // move to the next bit of the exponent, square (and mod) the base accordingly
        exponent >>= 1;
        base = (base * base) % modulus;
    }

    return result;
}

答案 1 :(得分:6)

Fast Modular Exponentiation(我认为这就是所谓的)可能有用。

Given a, b, c and a^b (mod c):

1. Write b as a sum of powers of 2. (If b=72, this is 2^6 + 2^3 )
2. Do:
    (1) a^2 (mod c) = a*
    (2) (a*)^2 (mod c) = a*
    (3) (a*)^2 (mod c) = a*
    ...
    (n) (a*)^2 (mod c) = a*

3. Using the a* from above, multiply the a* for the powers of 2 you identified. For example:
    b = 72, use a* at 3 and a* at 6.
    a*(3) x a*(6) (mod c)

4. Do the previous step one multiplication at a time and at the end, you'll have a^b % c.

现在,我不知道你将如何使用数据类型。只要你的数据类型可以支持c ^ 2,我想你会没事的。

如果使用字符串,只需创建加,减,乘的字符串版本(不要太难)。这种方法应该足够快。 (你可以用mod c开始第1步,这样a就不会大于c)。

编辑:哦,看看Modular Exponentiation上的维基页面。

答案 2 :(得分:4)

这是java中快速模块化指数(在早期答案之一中提出)的一个例子。不应该太难将其转换为C#

http://www.math.umn.edu/~garrett/crypto/a01/FastPow.html

和来源......

http://www.math.umn.edu/~garrett/crypto/a01/FastPow.java

答案 3 :(得分:2)

Python有pow(a,b,c)返回(a ** b)%c(只有更快),因此必须有一些聪明的方法来做到这一点。也许他们只是做你提到的身份。

答案 4 :(得分:1)

没有编写自己的fast modular exponentiation,我能提出的最简单的想法是使用F#BigInt类型:Microsoft.FSharp.Math.Types.BigInt支持任意大规模的操作 - 包括取幂和模运算。

这是一个内置类型,将在下一个版本中成为完整.NET框架的一部分。您不需要使用F#来使用BitInt - 您可以直接在C#中使用它。

答案 5 :(得分:1)

我建议检查Decimal文档并查看它是否符合您的要求,因为它是内置类型并且可以使用mod运算符。如果没有,那么你将需要像java的Bignum那样的任意精度库。

答案 6 :(得分:1)

你可以试试这个:

C#:对一个非常大的数字(&gt; Int64.MaxValue)进行模数(mod)操作
http://www.del337ed.com/blog/index.php/2009/02/04/c-doing-a-modulus-mod-operation-on-a-very-large-number-int64maxvalue/

答案 7 :(得分:1)

您可以尝试保理'a'到足够小的数字。

如果'a'的因子是'x','y'和'z',那么

a ^ b =(x ^ b)(y ^ b)(z ^ b)。

然后你可以使用你的身份:(a ^ b)%c =(a%c)^ b%c

答案 8 :(得分:1)

在我看来,电源和mod之间存在某种关系。权力只是重复乘法,而mod与分裂有关。我们知道乘法和除法是相反的,所以通过这种联系我会假设权力和模态之间存在相关性。

例如,取5的权力:

5 % 4 = 1
25 % 4 = 1
125 % 4 = 1
625 % 4 = 1
...

对于b的所有值,模式清楚,5 ^ b%4 = 1。

在这种情况下不太清楚:

5 % 3 = 2
25 % 3 = 1
125 % 3 = 2
625 % 3 = 1
3125 % 3 = 2
15625 % 3 = 1
78125 % 3 = 2
...

但仍有一种模式。

如果你可以计算模式背后的数学,如果你能在没有实际功率的情况下弄清楚mod的价值,我不会感到惊讶。

答案 9 :(得分:0)

你可以考虑a,b或c吗? C是否具有已知范围?

这些是32位整数!去检查这个site

例如,以下是如何得到n%d的mod,其中d 1>&gt; s(1,2,4,8,...)

  int n = 137;     // numerator
  int d = 32;      // denom d will be one of: 1, 2, 4, 8, 16, 32, ...
  int m;           // m will be n % d
  m = n & (d - 1); 

有n%d的代码,其中d是1>&gt; s - 1(1,3,7,15,31,...)

如果c很小,这只会非常有用,就像你说的那样。

答案 10 :(得分:-2)

看起来像加密中的作业。

提示:查看Fermat's little theorem