简体   繁体   中英

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

345227121439310000000000000 % 437 = 48

48 ^ 61 = 3,5951372914138399900210185557119e+102

3,5951372914138399900210185557119e+102 % 437 = 110

But, using my code i get these results:

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

For those who can't see the image, the results are:

val = 337 vf = 6

Neither 110^13 nor 48^61 are exactly representable using 64 bit double precision. 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 .

Double has far from enough precision for your case. Double is precise to 16 digits . Your values have 26 and 102 digits respectively. The digits that cannot be represented are simply lost, resulting in lost of precision.

You should be using some kind of bigint library:

The reason it doesn't work using doubles is because the double data type does not have sufficient precision. Large numbers such as 110^13 are not representable exactly as a double - they lose quite a lot of significant digits.

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 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.

Also note that you can make use of an implicit constructor which converts an int to a BigInteger , which simplifies the above code to:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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