Java-有没有欧几里德模或落地模的方法

Java-有没有欧几里德模或落地模的方法,java,operators,modulo,modulus,negative-number,Java,Operators,Modulo,Modulus,Negative Number,Java模运算符%基于截断除法(请参阅) 5%3产生2(注意5/3产生1) 5%(-3)产生2(注意5/(-3)产生-1) (-5)%3产生-2(注意(-5)/3产生-1) (-5)%(-3)产生-2(注意(-5)/-3)产生1) 在计算科学中,给定两个整数a和n,n>0,有时可以得到[a,n[内唯一的整数r,它与a模n一致 问题: Java中是否有一个高效的泛型运算符/方法遵守这个模的规范 这是为了避免在每个需要它的项目中重写它 混杂的 我在stackoverflow上发现了很多关于这个问

Java模运算符
%
基于截断除法(请参阅)

  • 5%3
    产生
    2
    (注意
    5/3
    产生
    1
  • 5%(-3)
    产生
    2
    (注意
    5/(-3)
    产生
    -1
  • (-5)%3
    产生
    -2
    (注意
    (-5)/3
    产生
    -1
  • (-5)%(-3)
    产生
    -2
    (注意
    (-5)/-3)
    产生
    1
在计算科学中,给定两个整数
a
n
n
>0,有时可以得到
[a,n[
内唯一的整数
r
,它与
a
n
一致

问题: Java中是否有一个高效的泛型运算符/方法遵守这个模的规范

这是为了避免在每个需要它的项目中重写它

混杂的 我在stackoverflow上发现了很多关于这个问题的问题,其中大多数都混淆了不同的模实现。如果您只是对负数的模运算结果感到不安,下面是一些基于Java
%
运算符的实现,它们可能很有用

普通黑客 由于我们几乎不使用负除数,因此当
n>0
时,此实现返回欧几里德模或落地模

static int mod(int a, int n){    
  return a<0 ? (a%n + n)%n : a%n;
}
  • 欧几里德模(5,3)
    产生
    2
  • 欧几里德模(-5,3)
    产生
    1
  • 欧几里德模(5,-3)
    产生
    2
  • 欧几里德模(-5,-3)
    产生
    1
地板模
static int floorredmodulo(int a,int n){
return n这个代码怎么样

public static int gcd(int p, int q) {
    if(count == 0) 
        System.out.print("Gcd for " + p + " and " + q);
    if (q == 0) {
           System.out.println(" returns " + p + " after " + count + " iterations");
        return p;
    }
    count++;
    return gcd(q, p % q);
}
public static void main(String[] args) {
    count = 0;
    gcd(4, 16);
    count = 0;
    gcd(4, 16);
    count = 0;
    gcd(16, 4);
    count = 0;
    gcd(15, 60);
    count = 0;
    gcd(15, 65);
    count = 0;
    gcd(1052, 52);
}
地板除法与模 自Java8以来,您可以在
java.lang.Math
中使用方法。请参阅和

欧氏除法与模 a) 基于截断除法
你可能已经检查过了,但是你可以很容易地使用
Math.floor()
()@Killrawr
Math.floor()
比上面的任何解决方案都差。@Killrawr
a-n*(int)Math.floor((双)a/n)
在数学上对于地板模是正确的,但不是有效的,也不是通用的。@boumbh您想要什么行为?应该给
(-5)magicmod(-3)
什么?
-2
2
?哈哈,我还没有尝试过这个问题中的任何解决方案(寻找改进)。但无论如何,感谢您对UmNyobe(+1 rep)的澄清。通常我在数学库中找到的大多数函数都很好,尽管像cos/sin/tan/pow/sqrt/log/exp。但是我还没有真正编写任何关于地板/天花板函数的代码(对不起,我帮不了什么忙).Hi Vlastimil,谢谢关于Java 8的好消息。我对您的实现有一些问题。当我尝试版本a)和版本b时,
euclideanMod(-4,-2)
返回2而不是0,对于版本c),
euclideanModA(5,-3)
返回了2而不是1。也许我做错了什么,你能确认吗?我读了你的评论,我错了,我需要时间来纠正。但是你可能在实现a)和b)中有错误?不,你是对的。事实上,我把答案作为草稿发送了-我不希望有人在下周末之前测试它。我想要的是“没有如果”您的解决方案的替代方案-说我正在考虑将a)和b)全部删除。@boumbh,我放弃了没有IFs的想法,只是用Java 8源代码启发自己。我会使用基于截断除法的欧几里德模,因为这是Java中的默认除法。但是绝对模算法更容易记住。嗨,Vlastill,我最后对它进行了测试。我对截断版本如此之快感到惊讶。我会认为类似
int r=x%y;return r>=0?r:r+Math.abs(y);
会更快,因为只有一个除法,没有乘法……你的截断版本是我目前发现的最快的。
static int flooredModulo(int a, int n){
  return n<0 ? -flooredModulo(-a, -n) : mod(a, n);
}
public static int gcd(int p, int q) {
    if(count == 0) 
        System.out.print("Gcd for " + p + " and " + q);
    if (q == 0) {
           System.out.println(" returns " + p + " after " + count + " iterations");
        return p;
    }
    count++;
    return gcd(q, p % q);
}
public static void main(String[] args) {
    count = 0;
    gcd(4, 16);
    count = 0;
    gcd(4, 16);
    count = 0;
    gcd(16, 4);
    count = 0;
    gcd(15, 60);
    count = 0;
    gcd(15, 65);
    count = 0;
    gcd(1052, 52);
}
+----+----+-----------+---------+-----------+-----------+---------+-----------+ | x mod y | quotient 'q' | remainder 'r' | | x | y | truncated | floored | Euclidean | truncated | floored | Euclidean | +----+----+-----------+---------+-----------+-----------+---------+-----------+ | 5 | 3 | 1 | 1 | 1 | 2 | 2 | 2 | | -5 | 3 | -1 | -2 | -2 | -2 | 1 | 1 | | 5 | -3 | -1 | -2 | -1 | 2 | -1 | 2 | | -5 | -3 | 1 | 1 | 2 | -2 | -2 | 1 | +----+----+-----------+---------+-----------+-----------+---------+-----------+
static int truncatedDiv(int x, int y) {    
    return x / y;
}

static int truncatedMod(int x, int y) {    
    return x % y;
}
static int floorDiv(int x, int y) {    
    return Math.floorDiv(x, y);
}

static int floorMod(int x, int y) {    
    return Math.floorMod(x, y);
}
import static java.lang.Math.*;

static int euclideanDiv(int x, int y) {
    int r = x / y;
    // if the divident is negative and modulo not zero, round down for positive divisor, otherwise round up
    if (x < 0 && r * y != x) {
        r -= signum(y);
    }
    return r;
}

static int euclideanMod(int x, int y) {
    int r = x - euclideanDiv(x, y) * y;
    return r;
}
import static java.lang.Math.*;

static int euclideanDiv(int x, int y) {
    int r = floorDiv(x, y);
    // if the divisor is negative and modulo not zero, round up
    if (y < 0 && r * y != x) {
        r++;
    }
    return r;
}

static int euclideanMod(int x, int y) {
    int r = x - euclideanDiv(x, y) * y;
    return r;
}
import static java.lang.Math.*;

static int euclideanMod(int x, int y) {
    int r = abs(x) % abs(y);
    // apply the sign of divident and make sure the remainder is positive number
    r *= signum(x);
    r = (r + abs(y)) % abs(y);
    return r;
}