原帖请见:看到一个面试题,大家来讨论下!
因为那个帖子太长了,我结了。这个帖子里主要贴几个典型的解法。我认为比较好的解法(在Blog里也写了这个方法:不用比较运算符,判断int型的a,b两数的大小)
public class Bigger {
public static void main(String args[]){
int a = -2147483648;
int b = 2147483647;
String[] strArray = {"a>=b", "a<b"};
int i = (int)((long)a-(long)b >>> 63);
System.out.println(strArray[i]);
}
}
然后我在回帖中看到了几个很典型的方法(注意:不用比较运算符,不用类库方法。)
System.out.println(a-b); //无语,那还不如int a=1; int b=2;直接拿眼睛看算了。
if(!(a-b))
{ if(abs(a-b)-(a-b))
{
return "a < b";
}
else
{
return "a > b";
}
}
else
{
return "a = b";
}//方法很好,数学里整数能到无穷大,但是计算机里不行啊。
public String compare(Integer x,Integer y){
String [] buf={"=>"," <"};
int id1=(x-y)>>>31;
System.out.println(id1);
return buf[id1];
}//也是没有考虑越界问题还有些是用接口实现的,有点复杂了。有很多人会问,搞这个东西有什么实际的用途吗?是,确实没什么用,不如直接比较。但是有时候我们中国人就是被这种“有没有用”的功利主义给害了。研究数学,物理和化学有用吗?是没有直接的作用,但是你看看为什么美国,日本,德国的工业和高科技产业如此发达,还不是靠基础科学的投入吗?Google为了提高搜索算法的效率,也是投入巨资。不是什么东西有用没用就能简单的决定你去不去做一件事情,因为你不去做一件事情,就无法知道你在做这件事情的过程中会有什么收获。有一句话说的好:人生是曲折的,但生活是精彩的。
因为那个帖子太长了,我结了。这个帖子里主要贴几个典型的解法。我认为比较好的解法(在Blog里也写了这个方法:不用比较运算符,判断int型的a,b两数的大小)
public class Bigger {
public static void main(String args[]){
int a = -2147483648;
int b = 2147483647;
String[] strArray = {"a>=b", "a<b"};
int i = (int)((long)a-(long)b >>> 63);
System.out.println(strArray[i]);
}
}
然后我在回帖中看到了几个很典型的方法(注意:不用比较运算符,不用类库方法。)
System.out.println(a-b); //无语,那还不如int a=1; int b=2;直接拿眼睛看算了。
if(!(a-b))
{ if(abs(a-b)-(a-b))
{
return "a < b";
}
else
{
return "a > b";
}
}
else
{
return "a = b";
}//方法很好,数学里整数能到无穷大,但是计算机里不行啊。
public String compare(Integer x,Integer y){
String [] buf={"=>"," <"};
int id1=(x-y)>>>31;
System.out.println(id1);
return buf[id1];
}//也是没有考虑越界问题还有些是用接口实现的,有点复杂了。有很多人会问,搞这个东西有什么实际的用途吗?是,确实没什么用,不如直接比较。但是有时候我们中国人就是被这种“有没有用”的功利主义给害了。研究数学,物理和化学有用吗?是没有直接的作用,但是你看看为什么美国,日本,德国的工业和高科技产业如此发达,还不是靠基础科学的投入吗?Google为了提高搜索算法的效率,也是投入巨资。不是什么东西有用没用就能简单的决定你去不去做一件事情,因为你不去做一件事情,就无法知道你在做这件事情的过程中会有什么收获。有一句话说的好:人生是曲折的,但生活是精彩的。
import java.util.Random;/**
* 不通过比较运算和类库,比较两个 integer 大小
*/
public class SimpleCompare { public static void main(String[] args) {
Random r = new Random();
int a = r.nextInt(), b = r.nextInt();
// int a = 33, b = 33; String[] results = {"a < b", "a == b", "a > b"}; int sum = 1;
sum = sum - (int)((long)(a - b) >>> 63);
sum = sum + (int)((long)(b - a) >>> 63);
System.out.println(a + ", " + b + ": " + results[sum]);
}
}
(long)(a-b)这样是不行的,a-b的结果仍然是个int型,然后再去转成long,这时的值可能已经不是想要的了。
{
System.out.println("a > b");
}
else
{
System.out.println("a < b");
}分析一下,呵呵
如果a>b,则|a-b|即为a-b
则(|a-b|+|a+b|)/2 = (a-b+a+b)/2 = a
如果a<b,则|a-b|即为b-a
则(|a-b|+|a+b|)/2 = (b-a+a+b)/2 = b因此(|a-b|+|a+b|)/2总返回二者中的较大者,由此可判断二者的大小
int a = -2147483648;
int b = 2147483647;
System.out.println(max(a, b));
} public static int max(int a, int b) {
int k = (~(a ^ b) >>> 31) * (a - b) >>> 31;
k += ((a ^ b) >>> 31) * (a >>> 31);
return b * k + a * (k ^ 1);
}
}
public class Compare {
private static final boolean signToBool[] = { true, false }; private static final boolean getSignOfInteger(int integer) {
return signToBool[integer >>> 31];
} public static boolean compareInteger(int int1, int int2) {
boolean signOfInt1 = getSignOfInteger(int1);
boolean signOfInt2 = getSignOfInteger(int2);
boolean signInt1MinusInt2 = getSignOfInteger(int1 - int2);
return (!(signOfInt1 ^ signOfInt2) && signInt1MinusInt2)
|| ((signOfInt1 ^ signOfInt2) && signOfInt1);
}
}
测试代码:
import java.util.Calendar;
import java.util.Random;import junit.framework.TestCase;public class CompareTest extends TestCase { public void testCompareWithSimpleIntegers() {
assertTrue(Compare.compareInteger(1, 1));
assertTrue(Compare.compareInteger(0, 0));
assertTrue(Compare.compareInteger(-1, -1)); assertTrue(Compare.compareInteger(1, 0));
assertTrue(Compare.compareInteger(0, -1));
assertTrue(Compare.compareInteger(2, 1));
assertTrue(Compare.compareInteger(1, -1));
assertTrue(Compare.compareInteger(-1, -2)); assertFalse(Compare.compareInteger(0, 1));
assertFalse(Compare.compareInteger(-1, 0));
assertFalse(Compare.compareInteger(1, 2));
assertFalse(Compare.compareInteger(-1, 1));
assertFalse(Compare.compareInteger(-2, -1));
} public void testCompareWithLargeIntegers() {
assertTrue(Compare.compareInteger(Integer.MAX_VALUE, Integer.MAX_VALUE));
assertTrue(Compare.compareInteger(Integer.MAX_VALUE, 0));
assertTrue(Compare.compareInteger(Integer.MAX_VALUE, -1));
assertTrue(Compare.compareInteger(Integer.MAX_VALUE, Integer.MIN_VALUE));
assertFalse(Compare.compareInteger(0, Integer.MAX_VALUE));
assertFalse(Compare.compareInteger(-2, Integer.MAX_VALUE)); assertTrue(Compare.compareInteger(Integer.MIN_VALUE, Integer.MIN_VALUE));
assertFalse(Compare.compareInteger(Integer.MIN_VALUE, 0));
assertFalse(Compare
.compareInteger(Integer.MIN_VALUE, Integer.MAX_VALUE));
assertTrue(Compare.compareInteger(-1, Integer.MIN_VALUE));
assertTrue(Compare.compareInteger(0, Integer.MIN_VALUE));
} public void testCompareWithRandomIntegers() {
Random random = new Random();
random.setSeed(Calendar.getInstance().getTimeInMillis());
int countOfTestDatas = 10000;
for (int i = 0; i < countOfTestDatas; i++) {
int a = random.nextInt();
int b = random.nextInt();
assertEquals(Compare.compareInteger(a, b), a >= b);
}
}
}
int b = 2147483647; // a 和 b 是否相等,相等时 e 值为 0,否则为 1
// 采用对半位或,逐次降位进行计算
int e = a ^ b;
e = (e & 0xffff0000) >>> 16 | (e & 0x0000ffff);
e = (e & 0x0000ff00) >>> 8 | (e & 0x000000ff);
e = (e & 0x0000000f) >>> 4 | (e & 0x0000000f);
e = (e & 0x0000000c) >>> 2 | (e & 0x00000003);
e = (e & 0x00000002) >>> 1 | (e & 0x00000001); // 进行比较,a 大时 k 值为 0,b 大时 k 值为 1,a 和 b 相等时 k 值为 0
int k = (~(a ^ b) >>> 31) * (a - b) >>> 31;
k += ((a ^ b) >>> 31) * (a >>> 31); // 按照 <、=、> 的 ASCII 顺序,修正 ASCII 偏移量
// e = 0, k = 0 时表示相等,偏移 1
// e = 1, k = 0 时表示大于,偏移 2
// e = 1, k = 1 时表示小于,偏移 0
int offset = (e & (k ^ 1)) + (k ^ 1); System.out.printf("%d %3$c %2$d%n", a, b, '<' + offset); // System.out.println(a + " " + (char)('<' + offset) + " " + b);
}
}
// 使用boolean表示符号位,true为正,false为负
private static final boolean signToBool[] = { true, false }; // 取得整数的符号位
private static final boolean getSignOfInteger(int integer) {
return signToBool[integer >>> 31];
} // 比较int1和int2大小,int1>=int2返回true,否则返回false
public static boolean compareInteger(int int1, int int2) {
boolean signOfInt1 = getSignOfInteger(int1);
boolean signOfInt2 = getSignOfInteger(int2);
boolean signInt1MinusInt2 = getSignOfInteger(int1 - int2);
// 原理很简单:符号相同返回int1-int2的符号位(为正表示int1>=int2);不同返回int1的符号位
return (!(signOfInt1 ^ signOfInt2) && signInt1MinusInt2)
|| ((signOfInt1 ^ signOfInt2) && signOfInt1);
} public static int maxInteger(int int1, int int2) {
return compareInteger(int1, int2) ? int1 : int2;
}
}用符号位实现的
public static int compareIntegerC(int int1, int int2) {
int signbitOfInt1 = int1 >>> 31;
int singbitOfInt2 = int2 >>> 31;
int signbitOfInt1MinusInt2 = (int1 - int2) >>> 31;
int signbitOfInt2MinusInt1 = (int2 - int1) >>> 31;
return singbitOfInt2 - signbitOfInt1
+ ((1 - singbitOfInt2 + signbitOfInt1) & 1)
* (signbitOfInt2MinusInt1 - signbitOfInt1MinusInt2);
}
可有赋值那么大吗?
本人虽然没什么技术,现在做这个小项目都做不好。
但我只想通过这道面试题表达出自己的想法
{
public static void main(String args[])
{
int a=1;
int b=2;
System.out.println(compareNumbers(3,33));
}
public static String compareNumbers(int a,int b)
{
String s1=String.valueOf(a);
String s2=String.valueOf(b);
int result=0;
String s=null;
//如果两个符号相同
if(!(s1.contains("-")^s2.contains("-")))
{
result=a-b;
if(String.valueOf(result).contains("-"))
{
s=a+"<"+b;
}
else if(String.valueOf(result).startsWith("0"))
{
s=a+"="+b;
}
else
{
s=a+">"+b;
}
}
else
{
if(s1.contains("-"))
{
s=a+"<"+b;
}
else
{
s=a+">"+b;
}
}
return s;
}
}
可能不怎么好,硬凑的,也算解决问题了
四川 锦年科技 监控软件 www.jyear.cn
问题分情况讨论后,可以转化为更容易解决的子问题
我们知道,比较两个“非负整数”是容易的。构思下面这个函数
// 如果a>=b返回true,否则返回false
public boolean ge(int a, int b) {
int pos1 = (new int[][] { {
0, 1}
, {
2, 3}
}
)[a >>> 31][b >>> 31];
int m = (new int[] {
1, 0, 0, 0})[pos1] * a + (new int[] {
0, -1, 0, -1})[pos1] * b;
int n = (new int[] {
0, 0, -1, -1})[pos1] * a + (new int[] {
1, 0, 0, 0})[pos1] * b;
return (new boolean[] {true, false})[ (m - n) >>> 31];
}
public class TestGe { public boolean ge(int a, int b) {
int pos1 = (new int[][] { {
0, 1}
, {
2, 3}
}
)[a >>> 31][b >>> 31];
int m = (new int[] {
1, 0, 0, 0})[pos1] * a + (new int[] {
0, -1, 0, -1})[pos1] * b;
int n = (new int[] {
0, 0, -1, -1})[pos1] * a + (new int[] {
1, 0, 0, 0})[pos1] * b;
return (new boolean[] {true, false})[ (m - n) >>> 31];
} public TestGe() {
int a, b;
a = 100;
b = 99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 99;
b = 100;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 99;
b = 99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 100;
b = -99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 99;
b = -100;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 99;
b = -99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -100;
b = 99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -99;
b = 100;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -99;
b = 99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -100;
b = -99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -99;
b = -100;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -99;
b = -99;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -2147483648;
b = 2147483647;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 2147483647;
b = -2147483648;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = 2147483647;
b = 2147483646;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
a = -2147483648;
b = -2147483647;
System.out.println("a=" + a + "\t b=" + b + "\t ge(a,b)=" + ge(a, b));
} public static void main(String[] args) {
new TestGe();
}
}
public static void main(String args[]){
int a = -2147483648;
int b = 2147483647;
String[] strArray = {"a>=b", "a<b"};
int i = (int)((long)a-(long)b >>> 63);
System.out.println(strArray[i]);
}
}
不过听人说减法操作其实就是移位操作