用于计算模数反转的Java程序输出大于10的数字的负值

时间:2014-08-04 18:23:51

标签: java modular-arithmetic

import java.util.*;  

class ModuloInverse {

    static long mod = 1000000007;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long num = in.nextLong();
        System.out.println(m_inverse(num, mod));
    }

    static long m_inverse(long a, long p) {
        return m_pow(a, p - 2);
    }

    static long m_pow(long n, long m) {
        long result = 0;

        if (m == 1) {
            return (n % mod);
        }

        if (m % 2 == 0) {
            result = m_pow(n, m / 2);

            return ((result * result) % mod);
        } else {
            result = m_pow(n, (m - 1) / 2);

            return (((n % mod) * (result * result)) % mod);
        }
    }
}

这是我编写的java程序,用于计算乘法模数逆(模10 ^ 9 + 7)。但它给出负数作为大于10的数字的输出。 无法弄清楚出了什么问题。

2 个答案:

答案 0 :(得分:1)

But it gives negative numbers as output for numbers greater than 10

那是因为你已经达到positive overflow长,因此返回/从负溢出开始。

很长,当您到达minimum value of -2^63 and a maximum value of 2^63-1时,此值的范围为2^63-1,然后返回-2^63并从那里开始。

答案 1 :(得分:1)

我在底部的if语句中添加了几行调试行:

    if (m % 2 == 0) {
        result = m_pow(n, m / 2);
        System.out.println("m = " + m + ", result = " + result + ", returning " + ((result * result) % mod));
        return ((result * result) % mod);
    } else {
        result = m_pow(n, (m - 1) / 2);
        System.out.println("m = " + m + ", n % mod = " + (n % mod) + ", result = " + result + ", returning " + (((n % mod) * (result * result)) % mod));
        return (((n % mod) * (result * result)) % mod);
    }

当我使用值13运行它时,这是打印出的最后一行:

m = 1000000005, n % mod = 13, result = 846153852, returning -428497853

现在846153852×846153852×13> 2 63 ,因此您的代码溢出了Java long的范围。

mod是10 9 + 7,如果result介于0和mod之间,则result * result将不会更多超过10 18 ,当然小于1.1×10 18 。 a long可以容纳的最大正值约为9.2×10 18 ,因此一旦n超过9,result * result * n就有可能超过n = 13这个价值。据我所知,这首先发生在mod

模数为long的两个数字的乘积将永远不会超出Java return (((n % mod) * (result * result)) % mod); 的范围,但可能包含三个或更多数字的乘积。

解决此问题的一种方法是更换行

return (((n % mod) * ((result * result) % mod) % mod);

{{1}}