如何在java中计算((整数)^(双))%(整数)?

时间:2014-11-13 03:30:29

标签: java math

我正在尝试计算(10 ^ 5.102103)%24的值,即在Java中提升到功率5.102103模数24?

这是最好和最准确的方法,因为

int a;
double b;
int m;

计算(a^b)%m

a可以非常大,如10 ^ 9

b可以是任何double或float值,可以很大

和m是任何整数

示例---如何计算

的值
(10^10002.3443)%10000007

我知道Math.pow(a,b)函数仅适用于小a和b

BigInteger函数只使用modPow(a,b),其中a和b应该只是整数(如果我错了,请纠正我)

2 个答案:

答案 0 :(得分:3)

不幸的是,使用普通的Java数据类型无法获得正确的答案。如果使用double来存储指数,则会引入错误,因为double不会精确地存储大多数十进制数。当您撰写double b = 10002.3443;时,b中存储的数字实际为10002.34430000000065774656832218170166015625。即使它在打印时看起来像10002.3443,这也是Java打印数字的一种技巧 - 基本上它选择了具有由该double表示的最小小数位数的十进制数。

现在这种差异看起来微不足道。但10^10002.344310^10002.34430000000065774656832218170166015625之间的差异大约是3.346 x 10^9990,这是一个9991位的数字。现在,当我们应用模数运算符时,这种差异会变成什么?

(10^10002.34430000000065774656832218170166015625 % 10000007) - (10^10002.3443 % 10000007)
= (10^10002.34430000000065774656832218170166015625 - 10^10002.3443) % 10000007
= (3.346 x 10^9990) % 10000007 (approximately)

现在,任何人都猜到了实际发生的事情。但是,如果你在计算中的任何一点使用double,你就有更好的机会被闪电击中,而不是得到正确的答案。

另一个选项可能是BigDecimal。但问题是10^10002.3443是不合理的 - 它不是终止小数,因此无法在BigDecimal中正确表示。

因此,Java没有允许您执行要执行的计算的数据类型。

您将不得不创建自己的数据类型,然后找出如何进行所有位运算以实现取幂和模数。这是一个庞大的项目,我建议你先从自己获得数学博士学位。

(注意:显然,我使用^表示取幂,x表示上面的乘法,即使这不是正常的Java约定)

答案 1 :(得分:0)

让我们回想一下离散的数学!

鉴于y = a b (mod m),我们知道

y = ((a mod m)^b) mod m

例如,如果我们有

a = 2, b = 6, m = 5

提升到b的幂是6464 mod m为64 % 5 == 4。让我们检查一下我们的算法:

4 == ((a mod m)^b) mod m
4 == ((2 mod 5)^6) mod 5
...
4 == 64 % 5
4 == 4

这并没有太多帮助我们(以当前的形式),所以让我们在每一步都使用模数运算来挽救这一天。

int a = 10;
int m = 10000007;
double b = 10002.3443;
int holder = (int) b;
double delta = b - holder; // as close as we're going to get

int total = 1;

for (int i = 0; i < holder; i++) {
    total *= (a % m); // multiply by the modulus
    total %= m;       // take the modulus again
}

total *= (Math.round(Math.pow(a, delta)) % m);
total %= m;