简体   繁体   English

C#中的Mod:返回错误值

[英]Mod in C#: It returns a wrong value

Ok, here's my code: 好的,这是我的代码:

       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();

Here's the thing, if i do that using the calculator i'll get these results: 这就是事情,如果我使用计算器这样做,我将得到以下结果:

110 ^ 13 = 345227121439310000000000000 110 ^ 13 = 345227121439310000000000000

345227121439310000000000000 % 437 = 48 345227121439310000000000000437 = 48

48 ^ 61 = 3,5951372914138399900210185557119e+102 48 ^ 61 = 3,5951372914138399900210185557119e + 102

3,5951372914138399900210185557119e+102 % 437 = 110 3,5951372914138399900210210185557119e + 102437 = 110

But, using my code i get these results: 但是,使用我的代码,我得到了以下结果:

( http://imageshack.com/a/img537/1309/7l42tc.jpg ) http://imageshack.com/a/img537/1309/7l42tc.jpg

For those who can't see the image, the results are: 对于那些看不到图像的人,结果是:

val = 337 vf = 6 val = 337 vf = 6

Neither 110^13 nor 48^61 are exactly representable using 64 bit double precision. 使用64位双精度无法准确表示110^1348^61 The data type does not have sufficient precision to represent these values exactly. 数据类型的精度不足以精确地表示这些值。 Because you cannot represent your operands exactly, you are actually performing different arithmetic from that which you intend to perform. 因为您不能精确地表示您的操作数,所以实际上您执行的运算与您打算执行的运算不同。 Once you've been unable to represent the original operands, there is no hope of recovery. 一旦无法表示原始操作数,就没有恢复的希望。

You need to use a type with sufficient precision. 您需要使用足够精确的类型。 For instance, System.Numerics.BigInteger . 例如, System.Numerics.BigInteger

Double has far from enough precision for your case. Double无法满足您的情况。 Double is precise to 16 digits . Double 精确到16位数字 Your values have 26 and 102 digits respectively. 您的值分别为26和102位数字。 The digits that cannot be represented are simply lost, resulting in lost of precision. 无法表示的数字会丢失,从而导致精度下降。

You should be using some kind of bigint library: 您应该使用某种bigint库:

The reason it doesn't work using doubles is because the double data type does not have sufficient precision. 使用double不起作用的原因是因为double数据类型的精度不足。 Large numbers such as 110^13 are not representable exactly as a double - they lose quite a lot of significant digits. 大数字(例如110^13不能精确表示为两倍-它们会损失很多有效数字。

The solution is to calculate it using a type that can represent very large integers. 解决方案是使用可以表示非常大的整数的类型进行计算。

Here's how you can do it using BigInteger : 使用BigInteger如下:

BigInteger a = new BigInteger(110);
BigInteger b = new BigInteger(13);
BigInteger c = new BigInteger(437);

BigInteger val = BigInteger.ModPow(a, b, c);

Note how there's a specific method, ModPow() , that combines raising to a power and modulus. 请注意,有一个特定的方法ModPow() ,它将提高到幂和模数相结合。

Also note that you can make use of an implicit constructor which converts an int to a BigInteger , which simplifies the above code to: 还要注意,您可以使用隐式构造函数,该构造函数将int转换为BigInteger ,从而将上述代码简化为:

BigInteger val = BigInteger.ModPow(110, 13, 437);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM