我正在尝试计算(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应该只是整数(如果我错了,请纠正我)
答案 0 :(得分:3)
不幸的是,使用普通的Java数据类型无法获得正确的答案。如果使用double
来存储指数,则会引入错误,因为double
不会精确地存储大多数十进制数。当您撰写double b = 10002.3443;
时,b
中存储的数字实际为10002.34430000000065774656832218170166015625
。即使它在打印时看起来像10002.3443
,这也是Java打印数字的一种技巧 - 基本上它选择了具有由该double表示的最小小数位数的十进制数。
现在这种差异看起来微不足道。但10^10002.3443
和10^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的幂是64
。 64
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;