大整数算术 - 如何实现模数?

时间:2014-11-21 09:21:56

标签: java math arbitrary-precision integer-arithmetic

我想实现我自己的(简单)大/任意整数精度算术,首先是在Java中(因为我对语法比较熟悉),然后将其重写为C.

我对无限长度的数字进行加法,减法和乘法,现在我需要模数用于加密应用程序。

我将任意数字的数字存储在数组中,我按照以下指南来说明如何存储数字: How to handle very large numbers in Java without using java.math.BigInteger

所以例如我想计算

849465603662254214335539562 % 578907659710377778063722

当我有两个数组时:

int[] a = [8, 4, 9, 4, 6, 5, 6, 0, 3, 6, 6, 2, 2, 5, 4, 2, 1, 4, 3, 3, 5, 5, 3, 9, 5, 6, 2]
int[] b = [5, 7, 8, 9, 0, 7, 6, 5, 9, 7, 1, 0, 3, 7, 7, 7, 7, 8, 0, 6, 3, 7, 2, 2]

代表这些数字。

获得

的简单解决方案是什么
int[] c = modFunction(a, b)

感谢任何帮助。

4 个答案:

答案 0 :(得分:1)

方法1

我想出了这个方法;它不一定有效,但它有效。

请注意,您可以使用输入的长度(以数字形式)来计算其对数
您可以使用它来执行除法,因此也可以使用模数。

具体来说,首先注意

849465603662254214335539562 / (578907659710377778063722 * 1000) = 1.4...

因此

849465603662254214335539562 - 578907659710377778063722 * 1000 = 270557943951876436271817562

现在注意到

270557943951876436271817562 / (578907659710377778063722 * 100) = 4.6...

因此

270557943951876436271817562 - (578907659710377778063722 * 400) = 38994880067725325046328762

现在注意到

38994880067725325046328762 / (578907659710377778063722 * 10) = 6.7...

因此

38994880067725325046328762 - (578907659710377778063722 * 60) = 4260420485102658362505442

最后,请注意

4260420485102658362505442 / (578907659710377778063722 * 1) = 7.3...

因此

4260420485102658362505442 - (578907659710377778063722 * 7) = 208066867130013916059388

答案是208066867130013916059388

只需通过检查长度就可以轻松获得10的幂数,你可以通过乘法计算所有10种可能性并找出哪一个是非负的,可以计算出你需要减去哪一个。结果

方法2

只需使用乘法二元搜索商!然后使用商来找到余数。

答案 1 :(得分:1)

计算D mod M时,您可以从D中减去M的任意整数倍,而不会更改结果。如果使用商D/M的近似值减去,则可以更接近所需的模数。重复直到商0会给你答案。

while D >= M
  Q= some integer approximation of D / M
  D= D - Q.M

要得到这样的商近似值,请取K DM的最高有效数字,并计算Q=10^K.D/M的整数部分。这可以使用双精度算术方便地完成,并为您提供K个数字(最多可以使用K=15)。在减法之前添加len(D)-len(M)-K个零进行重新排列。

请注意,在KD(至M个数字的近似值)之后,在K数字后截断会导致商数出现小错误。 (我的猜测是Q上的最大误差是一个单位。)这个错误并不重要,因为只要你减去M的整数倍,D仍然是确切的价值。最后,您需要检查0<=D<M

在给定的示例849465603662254214335539562 mod 578907659710377778063722中,近似商为10^15.849465603662254 / 578907659710377 = 1467359412876373.,您需要添加-12个零(!)进行重新排列,即将小数点移到左侧并使用1467

然后849465603662254214335539562 - 1467 * 578907659710377778063722 = 208066867130013916059388是请求的模数。

答案 2 :(得分:0)

Modulo非常简单:

a % b = a - floor((a / b)) * b

你需要的只是整数除法(或一个floor()和一个除法),乘法,减法。我想你已经有了这些操作。

如果只有整数,则不需要floor()函数:

a % b = a - (a / b) * b

示例:

849465603662254214335539562 % 578907659710377778063722 =
849465603662254214335539562 - (849465603662254214335539562  / 578907659710377778063722) *  578907659710377778063722 =
849465603662254214335539562 - 1467 * 578907659710377778063722 =
849465603662254214335539562 - 849257536795124200419480174 =
208066867130013916059388

答案 3 :(得分:-2)

为什么你不想使用BigDecimal类?它具有remainder方法,可以完全按照您的要求进行操作。您可以查看source code of BigDecimal class以查看其实施方式。