好的,这是我的代码:
int a, b, c, d;
double v1, v2, v3, vf, val;
a = 110;
b = 13;
c = 437;
d = 61;
v1 = Convert.ToDouble(a);
v2 = Convert.ToDouble(b);
v3 = Convert.ToDouble(d);
val = Math.Pow(v1, v2);
val = val % c;
Console.WriteLine("O valor do primeiro MOD é: {0}", val);
vf = Math.Pow(val, v3);
vf = vf % c;
Console.WriteLine("O valor final é: {0}", vf);
Console.ReadKey();
这就是事情,如果我使用计算器这样做,我会得到这些结果:
110 ^ 13 = 345227121439310000000000000
345227121439310000000000000 % 437 = 48
48 ^ 61 = 3,5951372914138399900210185557119e + 102
3,5951372914138399900210185557119e + 102 % 437 = 110
但是,使用我的代码我得到了这些结果:
(http://imageshack.com/a/img537/1309/7l42tc.jpg)
对于那些看不到图像的人,结果如下:
val = 337 vf = 6
答案 0 :(得分:3)
使用64位双精度,110^13
和48^61
都不能完全表示。数据类型没有足够的精度来准确表示这些值。因为您无法准确表示操作数,所以实际上您执行的算术与您要执行的操作不同。一旦你无法代表原始的操作数,就没有恢复的希望。
您需要使用具有足够精度的类型。例如,System.Numerics.BigInteger
。
答案 1 :(得分:2)
Double远远不够精确。双倍是precise to 16 digits。您的值分别为26和102位。无法表示的数字会丢失,导致精度损失。
你应该使用某种bigint库:
答案 2 :(得分:1)
它使用双精度工作的原因是因为双精度数据类型没有足够的精度。像110^13
这样的大数字不能完全表示为双重数字 - 它们会丢失很多有效数字。
解决方案是使用可以表示非常大的整数的类型来计算它。
以下是使用BigInteger
:
BigInteger a = new BigInteger(110);
BigInteger b = new BigInteger(13);
BigInteger c = new BigInteger(437);
BigInteger val = BigInteger.ModPow(a, b, c);
请注意具体方法ModPow()
如何将提升与功率和模数相结合。
另请注意,您可以使用隐式构造函数将int
转换为BigInteger
,从而将上述代码简化为:
BigInteger val = BigInteger.ModPow(110, 13, 437);