【问题标题】:Java Modular Multiplicative InverseJava 模乘逆
【发布时间】:2016-09-11 16:00:17
【问题描述】:

我这辈子都不知道如何找到模乘逆模 5。我已经阅读了所有的 wiki 文章、观看了视频,甚至向同学寻求帮助,但找不到解决方案。我发现的所有东西要么是另一种编程语言,我不能在其中翻译成 Java(编程新手)和/或使用双精度数而不是整数,我只能根据教授的规范使用整数。这是我到目前为止写的类,在我弄清楚inverse()方法之前不能使用divide()方法:

public class ModInt {

    /**
     * the integer modulo base
     */
    private int base;

    /**
    *  the number
    */
    private int number;

    /**
     * creates the modulo 2 number 0
     */
    public ModInt()
    {
        base = 2;
        number = 0;
    }

    /**
     * creates a modulo b number n
     * @param n the number
     * @param b the base
     */
    public ModInt(int n, int b)
    {
       number = n;
       base = b;
    }

    /**
     * creates an equivalent number in the same integer modulo base as the specified integer modulo number.
     * @param m an integer modulo number
     */
    public ModInt(ModInt m)
    {
       number = m.number;
       base = m.base;
    }

    /**
     * gives the number of the integer modulo number.
     * @return the number
     */
    public int getNumber()
    {
        return number;
    }

    /**
     * gives the base of the specified integer modulo number.
     * @return the base
     */
    public int getBase()
    {
        return base;
    }

    /**
     * modifies the integer modulo number using the specified parameters
     * @param n the new number
     * @param b the new base
     */
    public void setModInt(int n, int b)
    {
       number = n;
       base = b;
    }

    /**
     * adds this integer modulo number and the specified integer modulo number
     * @param m an integer modulo number
     * @return the sum of this number and the specified number
     */
    public ModInt add(ModInt m)
    {
       return new ModInt((number + m.number) % base, base);     
    }

    /**
     * subtracts this integer modulo number and the specified integer modulo number
     * @param m an integer modulo number
     * @return the difference this number and the specified number
     */
    public ModInt subtract(ModInt m)
    {
        return new ModInt(((base - number + m.number) % base, base);
    }

    /**
     * multiplies this integer modulo number and the specified integer modulo number
     * @param m an integer modulo number
     * @return the product of this number and the specified number
     */
    public ModInt multiply(ModInt m)
    {
       return new ModInt((number * m.number) % base, base);
    }    

    /**
     * computes the inverse of this integer modulo number
     * @return the inverse of this number
     */
    public ModInt inverse()
    {
       return new ModInt();
    }

    /**
     * divides this integer modulo number and the specified integer modulo number
     * @param m an integer modulo number
     * @return the quotient of this number and the specified number
     */
    public ModInt divide(ModInt m)
    {
       return new ModInt();
    }    

    /**
     * give the string representation of an integer modulo number in the format
     * n(mod b), where n is the number and b is the base
     * @return a string representation of the integer modulo number in the format
     * n(mod b); for example 3(mod 5) is the representation of the number 
     * 3 in integer modulo base 5
     */
    public String toString()
    {
       return String.format("%d(mod %d)", number, base);
    }

}

我正在尝试编写 inverse() 方法,以便它返回整数模数的倒数 (mod 5)。现在,我让它只返回默认构造函数,这样在运行代码时错误就会消失。任何人都可以尝试解释如何仅使用整数类型、没有双精度类型或任何其他类型来找到模乘逆吗?这是我教授的解释,但我不明白:

乘法逆或简单的数字 n 的逆, 表示 n^(-1),以整数模基 b 表示,是一个数,当 乘以 n 等于 1;也就是说,n × n^(−1) ≡ 1(mod b)。为了 例如,5^(−1) 整数模 7 为 3,因为 (5 × 3) mod 7 = 15 mod 7 ≡ 1。 数字 0 没有倒数。不是每个数字都是可逆的。为了 例如,2^(-1) 整数模 4 是不确定的,因为 {0 中没有整数, 1, 2, 3}可以乘以2得到1。

感谢任何帮助,谢谢。

【问题讨论】:

  • 你有一些代码,但究竟是什么不起作用?!如果你能给出一些具体的例子来说明你的代码没有按照你期望的那样做,那将会很有帮助。不要指望我们为您做到这一点!
  • @GhostCat 抱歉,我已将我的问题更新为更具体。
  • PS 以下行System.out.println(new ModInt(2, 5).subtract(new ModInt(4, 5))); 打印-2(mod 5) — 是否符合预期?我可能期望 3(mod 5) 因为 3 + 4 等于 2 (mod 5)。
  • @OleV.V.是的,你是对的。我在上面编辑了我的方法。谢谢。

标签: java


【解决方案1】:

我从https://comeoncodeon.wordpress.com/2011/10/09/modular-multiplicative-inverse/ 获取了蛮力算法,它是用 C++ 编写的,但几乎编译为 Java。所以我的大部分工作都是调整它以适应你的班级。结果如下:

/**
 * computes the inverse of this integer modulo number
 * 
 * @return the inverse of this number
 */
public ModInt inverse() {
    int a = number % base;
    for (int x = 1; x < base; x++) {
        if ((a * x) % base == 1) {
            return new ModInt(x, base);
        }
    }
    throw new ArithmeticException("No inverse of " + toString());
}

【讨论】:

    【解决方案2】:

    应该这样做。如果am 不是相对质数(即有一个不是1 的公约数),这将返回一个-1

    如果am 不是相对质数,我在从1 to m 迭代之前包含了对gcd 方法的调用,以缩短过程。

    
         public static int mod(int a, int m) {
            if (gcd(a,m) != 1) {
                return -1;
            }
            int x;
            for (x = 1; x < m; x++) {
                if ((a * x) % m == 1) {
                    break;
                }
            }
            return x;
        }
        public static int gcd(int r, int s) {
            while (s != 0) {
               int t = s;
               s = r % s;
               r = t;
            }
            return r;
        }
    
    

    更多信息请查看Modular Multiplicative Inverse

    【讨论】:

      【解决方案3】:

      在进行乘法逆运算之前,这里有一些事实。

      给定等式:

      当且仅当有乘法逆 n>1 , gcd(a,n) = 1. 和 b =1

      因此等式变为:

      其中 a^{-1} 是 a 的乘法逆元。

      使用扩展的Eculid算法给定两个整数a,b; gcd(a,b) 可以写成 a 和 b 的线性组合,所以等式变为:

      我们需要找到 x 的值,它是 a 的乘法逆元。

      如果 x 的值为负数,则使用模算术的以下属性添加 n 使其为正数。

      这是执行相同操作的 java 代码:

      import java.math.BigInteger;
      
      public class ExtendedEculid {
      
          public static int[] egcd(int a, int b) {
              if (b == 0)
                  return new int[] { a, 1, 0 };
              else {
                  int[] arr = egcd(b, a % b);
      
                  int gcd = arr[0];
                  int X = arr[2];
                  int Y = arr[1] - (a / b) * arr[2];
      
                  return new int[] { gcd, X, Y };
              }
          }
      
          public static int multiplicativeInverse(int a, int modulo) {
      
              int[] egcdValues = egcd(a, modulo);
      
              // since multiplicative inverse exist iff gcd(a,modulo) =1
              // if no inverse exist then return 0
      
              if (egcdValues[0] != 1)
                  return 0;
              if (egcdValues[1] > 0)
                  return egcdValues[1];
              else
                  return egcdValues[1] + modulo;
          }
          
          
          public static void main(String[] args) {
              
              System.out.println(multiplicativeInverse(5, 7));
              
              // using BigInteger
              BigInteger a = new BigInteger("5");
              BigInteger m = new BigInteger("7");
              System.out.println(a.modInverse(m));
              
          }
      }
      

      编辑:java.math.BigInteger 有一个方法 modInverse here。你也可以使用它,为它添加了代码sn-p。

      参考:CLRS,算法简介,第 3 版,第 31 章

      【讨论】:

        【解决方案4】:

        你可以试试这个代码,你会找到答案:

        //package CNS;
        
        import java.util.Scanner;
        
        public class extended_eculidean {
        
            public static void extended_eculidean(int m,int b){
                int a1=1,a2=0,a3=b;
                int b1=0,b2=1,b3=m;
                int count=0;
        
                while(b3!=1 && b3!=0)
                {
                    int  q=a3/b3;
                    int  t1=(a1-(q*b1));
                    int t2=(a2-(q*b2));
                    int  t3=(a3-(q*b3));
                    //copying values of previous b1,b2,b3 into current a1,a2,a3
                    a1=b1;
                    a2=b2;
                    a3=b3;
                    b1=t1;
                    b2=t2;
                    b3=t3;
                }
        
                if(b3==0)
                {
                    System.out.println("Inverse can not found");
                }
                else
                {
                    if(b2<0) {
                        b2=b2+m;
                    }
                }
                System.out.println("the inverse found : that is the answer");
                System.out.println( b2);
            }
        
            public static void main(String[] args) {
                Scanner sc=new Scanner(System.in);
                System.out.println("enter the number :");
                int b=sc.nextInt();
        
                System.out.println("enter the number of galois field");
                int m=sc.nextInt();
        
                System.out.println("this is the answer" );
                extended_eculidean(m,b);
            }
        }
        

        输出:

        enter the number :
        17
        enter the number of galois field
        29
        this is the answer
        the inverse found: that is the answer
        22
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多