求大数取模的算法

LIDEHUA1975 2002-12-16 05:24:37
例如:2.8e999 % 23 = ?
这么大的数字没办法精确表示,该怎么办呢?是不是要用到同余定理之类的公式分解一下啊?
微软计算器给出的答案是10,真不知道他是怎么做的。
对于有用的提示,我一定给分。
...全文
1106 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
LIDEHUA1975 2002-12-29
  • 打赏
  • 举报
回复
1212,我的计算器只有微软计算器的功能,是应用在PDA上的。
1212 2002-12-28
  • 打赏
  • 举报
回复
RE:LIDEHUA1975(李逍遥) (
你的高精度科学计算器支持离散对数、因式分解功能吗?
Riemann 2002-12-18
  • 打赏
  • 举报
回复
首先你应该解决大数的表示问题,这可通过一个结构数组来实现。结构中含有两个成员:coef,exp,分别保存该数十进制表示的系数和指数。
在此基础上,在利用初等数论的一些性质,如:a^k mod n = (a mod n)^k等来计算。
LIDEHUA1975 2002-12-18
  • 打赏
  • 举报
回复
谢谢大家对我的帮助,非常感谢。
请接分。
其实我现在做的是一个高精度科学计算器项目,目前进展顺利,看来年终奖是少不了了。
呵呵!
strafer 2002-12-17
  • 打赏
  • 举报
回复
这算法是我抄来得,这应该算是初等数论里的只是了。 你可以找本书来看看。

下面是这个算法的原理: (a*b) mod n = ((a mod n)*(b mod n)) mod n

quote from "apply cryptography second edition"

For example, if you want to calculate a8 mod n, don’t use the naïve approach and perform seven multiplications and one huge modular reduction:

(a*a*a*a*a*a*a*a) mod n
Instead, perform three smaller multiplications and three smaller modular reductions:

((a^2 mod n)^2 mod n)^2 mod n
By the same token,

a^16 mod n = (((a^2 mod n)^2 mod n)^2 mod n)^2 mod n




LIDEHUA1975 2002-12-17
  • 打赏
  • 举报
回复
回复o3y:不错,我就是在做高精度模拟浮点运算库,偏移阶码15bit,有效位数144bit,目前刚开始测试,真是头疼啊。
LIDEHUA1975 2002-12-17
  • 打赏
  • 举报
回复
回复zzwu:其实我想解决的实际问题是这样的,在计算器中计算三角函数时,如果输入的参数很大,在将其化入2pi区间(相当于对2pi取模)时就变成0了,我现在的做法是ae = x / 2pi;ae = fix(ae)取整;be = x - ae*2*pi;因为x和ae*2*pi很大而且接近,所以相减结果就为0了。
所以我才想借鉴一下大数取模的算法,不过看来是行不通了。
但是也没什么要紧的了,因为精度有限(144bit),大数不计算也是可以理解的。
LIDEHUA1975 2002-12-17
  • 打赏
  • 举报
回复
strafer的程序对我有很大的帮助,谢谢了。
虽然我最终的目的是为了解决实数取模的问题,但你的功力仍然让我佩服。
djniulihao 2002-12-17
  • 打赏
  • 举报
回复
这是海星的大数乘法算法,希望对你有帮助
通常,在分析一个算法的计算复杂性时,都将加法和乘法运算当作是基本运算来处理,即将执行一次加法或乘法运算所需的计算时间当作一个仅取决于计算机硬件处理速度的常数。
这个假定仅在计算机硬件能对参加运算的整数直接表示和处理时才是合理的。然而,在某些情况下,我们要处理很大的整数,它无法在计算机硬件能直接表示的范围内进行处理。若用浮点数来表示它,则只能近似地表示它的大小,计算结果中的有效数字也受到限制。若要精确地表示大整数并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算。
设X和Y都是n位的二进制整数,现在要计算它们的乘积XY。我们可以用小学所学的方法来设计一个计算乘积XY的算法,但是这样做计算步骤太多,显得效率较低。如果将每2个1位数的乘法或加法看作一步运算,那么这种方法要作O(n2)步运算才能求出乘积XY。下面我们用分治策略来设计一个更有效的大整数乘积算法。
 

图1 大整数X和Y的分段 
我们将n位的二进制整数X和Y各分为2段,每段的长为n/2位(为简单起见,假设n是2的幂),如图1所示。
由此,X=A2n/2+B ,Y=C2n/2+D。这样,X和Y的乘积为:
XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD (1)
如果按式(1)计算XY,则我们必须进行4次n/2位整数的乘法(AC,AD,BC和BD),
以及3次不超过n位的整数加法(分别对应于式(1)中的加号),此外还要做2次移位(分别对应于式(1)中乘2n和乘2n/2)。所有这些加法和移位共用O(n)步运算。设T(n)是2个n位整数相乘所需的运算总数,则由式(1),我们有:
(2)
由此可得T(n)=O(n2)。因此,用(1)式来计算X和Y的乘积并不比小学生的方法更有效。要想改进算法的计算复杂性,必须减少乘法次数。为此我们把XY写成另一种形式:
XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD (3)
虽然,式(3)看起来比式(1)复杂些,但它仅需做3次n/2位整数的乘法(AC,BD和(A-B)(D-C)),6次加、减法和2次移位。由此可得:
(4)
用解递归方程的套用公式法可解得T(n)=O(nlog3)=O(n1.59)。利用式(3),并考虑到X和Y的符号对结果的影响,我们给出大整数相乘的完整算法Multiply如下:
Multiply(X,Y,n) △ X和Y为2个小于2n的整数,返回结果为X和Y的乘积XY
1. S ← sign(X) * sign(Y) △ S为X和Y的符号乘积}
2. X ← abs(X)
3. Y ← abs(Y) △ X和Y分别取绝对值}
4. if n = 1
5. then if (X = 1) and (Y = 1)
6. then return S
7. else return(0)
8. else A ← X的左边n/2位
9. B ← X的右边n/2位
10. C ← Y的左边n/2位
11. D ← Y的右边n/2位
12. m1 ← Multiply(A, C, n / 2)
13. m2 ← Multiply(A - B, D - C, n / 2)
14. m3 ← Multiply(B, D, n / 2)
15. S ← S * (m1 * 2n + (m1 + m2 + m3) * 2n/2 + m3)
16. return S
上述二进制大整数乘法同样可应用于十进制大整数的乘法以提高乘法的效率减少乘法次数。下面的例子演示了算法的计算过程。
设X=314l,Y=5327,用上述算法计算XY的计算过程可列表如下,其中带 ' 号的数值是在计算完成AC,BD,和(A-B)(D-C)之后才填入的。

X=3141 A=31 B=41 A-B=-10
Y=5327 C=53 D=27 D-C=-26
AC=(1643)'
BD=(1107)'
(A-B)(D-C)=(260)'
XY=(1643)'104+[(1643)'+(260)'+(1107)']102+(1107)'
=(16732107)'

A=31 A1=3 B1=1 A1-B1=2
C=53 C1=5 D1=3 D1-C1=-2
A1C1=15 B1D1=3 (A1-B1)(D1-C1)=-4
AC=1500+(15+3-4)10+3=1643

B=41 A2=4 B2=1 A2-B2=3
D=27 C2=2 D2=7 D2-C2=5
A2C2=8 B2D2=7 (A2-B2)(D2-C2)=15
BD=800+(8+7+15)10+7=1107

|A-B|=10 A3=1 B3=0 A3-B3=1
|D-C|=26 C3=2 D3=6 D3-C3=4
A3C3=2 B3D3=0 (A3-B3)(D3-C3)=4
(A-B)(D-C)=200+(2+0+4)10+0=260

如果将一个大整数分成3段或4段做乘法,计算复杂性会发生会么变化呢?是否优于分成2段做的乘法?这个问题请大家自己考虑。

o3y 2002-12-16
  • 打赏
  • 举报
回复
不会又是高精度吧……高精度的除法。
zzwu 2002-12-16
  • 打赏
  • 举报
回复
2.8e999 不是一个实型数吗? 取模的含义是什么?
strafer 2002-12-16
  • 打赏
  • 举报
回复
下面是实现a^x mod n的算法。
unsigned long qe2(unsigned long x, unsigned long y, unsigned long n) {
unsigned long s,t,u;
int i;

s = 1; t = x; u = y;
while(u) {
if(u&1) s = (s* t)%n;
u>>=1;
t = (t* t)%n;
}
return(s);
}




dcyu 2002-12-16
  • 打赏
  • 举报
回复
费尔马小定理:
10^22 mod 23 =1

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧