Java-有没有欧几里德模或落地模的方法
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上发现了很多关于这个问
%
基于截断除法(请参阅)
产生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()
()@KillrawrMath.floor()
比上面的任何解决方案都差。@Killrawra-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;
}