我在接受采访时被问及如何判断一个数字是正数还是负数。规则是我们不应该使用内置在java函数中的<
和>
等条件运算符(如substring
,indexOf
,charAt
和startsWith
),没有正则表达式或API。
我做了一些关于此的功课,下面给出了代码,但它只适用于整数类型。但是他们让我写了一个适用于float
,double
和long
的通用代码。
// This might not be better way!!
S.O.P ((( number >> 31 ) & 1) == 1 ? "- ve number " : "+ve number );
您身边的任何想法?
答案 0 :(得分:66)
整数个案很容易。双重情况比较棘手,直到你记得无穷大。
注意:如果你认为双常量是“api的一部分”,你可以用溢出的表达式替换它们,如1E308 * 2
。
int sign(int i) {
if (i == 0) return 0;
if (i >> 31 != 0) return -1;
return +1;
}
int sign(long i) {
if (i == 0) return 0;
if (i >> 63 != 0) return -1;
return +1;
}
int sign(double f) {
if (f != f) throw new IllegalArgumentException("NaN");
if (f == 0) return 0;
f *= Double.POSITIVE_INFINITY;
if (f == Double.POSITIVE_INFINITY) return +1;
if (f == Double.NEGATIVE_INFINITY) return -1;
//this should never be reached, but I've been wrong before...
throw new IllegalArgumentException("Unfathomed double");
}
答案 1 :(得分:36)
以下是一种可怕的方法,可以让你解雇任何工作......
这取决于你得到一个Stack Overflow Exception [或者Java所谓的]它...它只适用于那些不会像疯了一样偏离0的正数。
负数很好,因为你会溢出到正数,然后最终得到一个堆栈溢出异常[会返回false,或者“是,它是负面的”]
Boolean isPositive<T>(T a)
{
if(a == 0) return true;
else
{
try
{
return isPositive(a-1);
}catch(StackOverflowException e)
{
return false; //It went way down there and eventually went kaboom
}
}
}
答案 2 :(得分:17)
这仅适用于[0..2]
以外的所有内容boolean isPositive = (n % (n - 1)) * n == n;
你可以像这样做一个更好的解决方案(除了[0..1]之外的工作)
boolean isPositive = ((n % (n - 0.5)) * n) / 0.5 == n;
通过使用2 ^ m(m整数)更改0.5部分可以获得更好的精度:
boolean isPositive = ((n % (n - 0.03125)) * n) / 0.03125 == n;
答案 3 :(得分:8)
您可以这样做:
((long) (num * 1E308 * 1E308) >> 63) == 0 ? "+ve" : "-ve"
这里的主要思想是我们投入很长时间并检查最重要位的值。当-1和0之间的double / float在转换为long时将舍入为零,我们乘以大的double,以便负float / double小于-1。由于subnormals的存在,需要两次乘法(虽然它确实不需要那么大)。
答案 4 :(得分:4)
这个怎么样?
return ((num + "").charAt(0) == '-');
答案 5 :(得分:3)
// Returns 0 if positive, nonzero if negative
public long sign(long value) {
return value & 0x8000000000000000L;
}
请致电:
long val1 = ...;
double val2 = ...;
float val3 = ...;
int val4 = ...;
sign((long) valN);
从double / float / integer转换为long应该保留符号,如果不是实际值......
答案 6 :(得分:3)
你说
我们不应该使用条件运算符
但这是一个技巧要求,因为==
也是一个条件运算符。还有一个内置于? :
,while
和for
循环中的内容。因此几乎每个人都未能提供满足所有要求的答案。
在没有条件运算符的情况下构建解决方案的唯一方法是在满足条件之前使用查找表与其他一些可以归结为0/1或字符的解决方案之一。
以下是我认为可能与查找表相关的答案:
答案 7 :(得分:2)
此代码涵盖所有案例和类型:
public static boolean isNegative(Number number) {
return (Double.doubleToLongBits(number.doubleValue()) & Long.MIN_VALUE) == Long.MIN_VALUE;
}
此方法接受任何包装类(Integer
,Long
,Float
和Double
),并且感谢自动装入任何原始数字类型({ {1}},int
,long
和float
)只需检查高位,即所有类型的符号位都设置。
在通过以下任何一项时返回double
:
true
/ int
Integer
/ long
Long
/ float
Float
/ double
Double
Double.NEGATIVE_INFINITY
和Float.NEGATIVE_INFINITY
否则。
答案 8 :(得分:2)
此解决方案使用模数。是的,它也适用于0.5
(测试在下面,在主要方法中)。
public class Num {
public static int sign(long x) {
if (x == 0L || x == 1L) return (int) x;
return x == Long.MIN_VALUE || x % (x - 1L) == x ? -1 : 1;
}
public static int sign(double x) {
if (x != x) throw new IllegalArgumentException("NaN");
if (x == 0.d || x == 1.d) return (int) x;
if (x == Double.POSITIVE_INFINITY) return 1;
if (x == Double.NEGATIVE_INFINITY) return -1;
return x % (x - 1.d) == x ? -1 : 1;
}
public static int sign(int x) {
return Num.sign((long)x);
}
public static int sign(float x) {
return Num.sign((double)x);
}
public static void main(String args[]) {
System.out.println(Num.sign(Integer.MAX_VALUE)); // 1
System.out.println(Num.sign(1)); // 1
System.out.println(Num.sign(0)); // 0
System.out.println(Num.sign(-1)); // -1
System.out.println(Num.sign(Integer.MIN_VALUE)); // -1
System.out.println(Num.sign(Long.MAX_VALUE)); // 1
System.out.println(Num.sign(1L)); // 1
System.out.println(Num.sign(0L)); // 0
System.out.println(Num.sign(-1L)); // -1
System.out.println(Num.sign(Long.MIN_VALUE)); // -1
System.out.println(Num.sign(Double.POSITIVE_INFINITY)); // 1
System.out.println(Num.sign(Double.MAX_VALUE)); // 1
System.out.println(Num.sign(0.5d)); // 1
System.out.println(Num.sign(0.d)); // 0
System.out.println(Num.sign(-0.5d)); // -1
System.out.println(Num.sign(Double.MIN_VALUE)); // -1
System.out.println(Num.sign(Double.NEGATIVE_INFINITY)); // -1
System.out.println(Num.sign(Float.POSITIVE_INFINITY)); // 1
System.out.println(Num.sign(Float.MAX_VALUE)); // 1
System.out.println(Num.sign(0.5f)); // 1
System.out.println(Num.sign(0.f)); // 0
System.out.println(Num.sign(-0.5f)); // -1
System.out.println(Num.sign(Float.MIN_VALUE)); // -1
System.out.println(Num.sign(Float.NEGATIVE_INFINITY)); // -1
System.out.println(Num.sign(Float.NaN)); // Throws an exception
}
}
答案 9 :(得分:1)
未经测试,但说明了我的想法:
boolean IsNegative<T>(T v) {
return (v & ((T)-1));
}
答案 10 :(得分:1)
在没有代码的情况下尝试此操作:(x-SQRT(x^2))/(2*x)
答案 11 :(得分:1)
我认为有一个非常简单的解决方案:
public boolean isPositive(int|float|double|long i){
return (((i-i)==0)? true : false);
}
告诉我,如果我错了!
答案 12 :(得分:1)
这个大致基于ItzWarty的答案,但它在登录时间运行!警告:仅适用于整数。
Boolean isPositive(int a)
{
if(a == -1) return false;
if(a == 0) return false;
if(a == 1) return true;
return isPositive(a/2);
}
答案 13 :(得分:1)
如果是有效答案
boolean IsNegative(char[] v) throws NullPointerException, ArrayIndexOutOfBoundException
{
return v[0]=='-';
}
答案 14 :(得分:1)
我能想到的另一个选择
private static boolean isPositive(Object numberObject) {
Long number = Long.valueOf(numberObject.toString());
return Math.sqrt((number * number)) != number;
}
private static boolean isPositive(Object numberObject) {
Long number = Long.valueOf(numberObject.toString());
long signedLeftShifteredNumber = number << 1; // Signed left shift
long unsignedRightShifterNumber = signedLeftShifteredNumber >>> 1; // Unsigned right shift
return unsignedRightShifterNumber == number;
}
答案 15 :(得分:1)
整数是微不足道的;你已经知道了。深层问题是如何处理浮点值。那时,您必须更多地了解浮点值的实际工作方式。
密钥为Double.doubleToLongBits(),可让您获取该数字的IEEE表示形式。 (该方法实际上是直接演绎,对于处理NaN值有一点魔力。)一旦将double转换为long,您可以使用0x8000000000000000L作为掩码来选择符号位;如果为零,则该值为正,如果为1,则为负。
答案 16 :(得分:1)
这对我来说似乎是随意的,因为我不知道你如何得到任何类型的数字,但是如何检查Abs(数字)!=数字?也许&amp;&amp;号码!= 0
答案 17 :(得分:0)
以下情况如何?
T sign(T x) {
if(x==0) return 0;
return x/Math.abs(x);
}
应该适用于每种类型的T ...
或者,可以将abs(x)定义为Math.sqrt(x * x), 如果这也是作弊,请实现自己的平方根函数......
答案 18 :(得分:0)
使用条件写它然后看一下生成的汇编代码。
答案 19 :(得分:0)
这很容易就像
一样private static boolean isNeg(T l) {
return (Math.abs(l-1)>Math.abs(l));
}
答案 20 :(得分:0)
有一个函数是数学库,名为signnum。
http://www.tutorialspoint.com/java/lang/math_signum_float.htm http://www.tutorialspoint.com/java/lang/math_signum_double.htm
答案 21 :(得分:0)
两个简单的解决方案。也适用于无穷大和数字-1&lt; = r&lt; = 1 将为NaN返回“正面”。
String positiveOrNegative(double number){
return (((int)(number/0.0))>>31 == 0)? "positive" : "negative";
}
String positiveOrNegative(double number){
return (number==0 || ((int)(number-1.0))>>31==0)? "positive" : "negative";
}
答案 22 :(得分:0)
组合泛型与双API。猜猜这有点作弊,但至少我们只需要编写一种方法:
static <T extends Number> boolean isNegative(T number)
{
return ((number.doubleValue() * Double.POSITIVE_INFINITY) == Double.NEGATIVE_INFINITY);
}
答案 23 :(得分:0)
if (((Double)calcYourDouble()).toString().contains("-"))
doThis();
else doThat();
答案 24 :(得分:0)
好吧,利用铸造(因为我们不关心实际值是什么),也许以下方法可行。请记住,实际的实现不违反API规则。我编辑了这个以使方法名称更明显,并根据@chris关于{-1,+ 1}问题域的评论。从本质上讲,如果不依赖于Float或Double中引用float和double原语的本地位结构的API方法,这个问题似乎无法解决。
正如其他人所说:愚蠢的面试问题。 GRR。
public class SignDemo {
public static boolean isNegative(byte x) {
return (( x >> 7 ) & 1) == 1;
}
public static boolean isNegative(short x) {
return (( x >> 15 ) & 1) == 1;
}
public static boolean isNegative(int x) {
return (( x >> 31 ) & 1) == 1;
}
public static boolean isNegative(long x) {
return (( x >> 63 ) & 1) == 1;
}
public static boolean isNegative(float x) {
return isNegative((int)x);
}
public static boolean isNegative(double x) {
return isNegative((long)x);
}
public static void main(String[] args) {
// byte
System.out.printf("Byte %b%n",isNegative((byte)1));
System.out.printf("Byte %b%n",isNegative((byte)-1));
// short
System.out.printf("Short %b%n",isNegative((short)1));
System.out.printf("Short %b%n",isNegative((short)-1));
// int
System.out.printf("Int %b%n",isNegative(1));
System.out.printf("Int %b%n",isNegative(-1));
// long
System.out.printf("Long %b%n",isNegative(1L));
System.out.printf("Long %b%n",isNegative(-1L));
// float
System.out.printf("Float %b%n",isNegative(Float.MAX_VALUE));
System.out.printf("Float %b%n",isNegative(Float.NEGATIVE_INFINITY));
// double
System.out.printf("Double %b%n",isNegative(Double.MAX_VALUE));
System.out.printf("Double %b%n",isNegative(Double.NEGATIVE_INFINITY));
// interesting cases
// This will fail because we can't get to the float bits without an API and
// casting will round to zero
System.out.printf("{-1,1} (fail) %b%n",isNegative(-0.5f));
}
}
答案 25 :(得分:0)
为什么不获得数字的平方根?如果它是否定的 - java将抛出一个错误,我们将处理它。
try {
d = Math.sqrt(THE_NUMBER);
}
catch ( ArithmeticException e ) {
console.putln("Number is negative.");
}
答案 26 :(得分:0)
此解决方案不使用条件运算符,但依赖于捕获两个删除。
除法错误等同于最初为“否定”的数字。或者,如果数字是正数,则该数字最终会从行星上掉落并抛出StackOverFlow异常。
public static boolean isPositive( f)
{
int x;
try {
x = 1/((int)f + 1);
return isPositive(x+1);
} catch (StackOverFlow Error e) {
return true;
} catch (Zero Division Error e) {
return false;
}
}
答案 27 :(得分:0)
效率不高,但我想这里并不重要:(我对Java也有点生疏,我希望这或多或少是正确的语法。)
boolean isPositive = false;
int n = (int)(x * x);
while (n-- != 0)
{
if ((int)(--x) == 0)
{
isPositive = true;
break;
}
}
这应该有效,因为x
最多会减少x * x
次(总是一个正数),如果x
永远不等于0,那么它必须是负数才能开始用。另一方面,如果x
在某个时刻等于0,则必须是正面的。
请注意,这会导致isPositive
为false
为0。
P.S。:不可否认,这不适用于非常大的数字,因为(int)(x * x)
会溢出。
答案 28 :(得分:0)
如果你被允许使用“==”似乎就是这种情况,那么你可以利用这样一个事实,即如果一个数组索引超出界限就会引发异常。代码是double,但你可以将任何数字类型转换为double(这里最终的精度损失根本不重要)。
我添加了注释来解释这个过程(带上值-2.0; -1.0)union [1.0; 2.0 [)以及一个小的测试驱动程序。
class T {
public static boolean positive(double f)
{
final boolean pos0[] = {true};
final boolean posn[] = {false, true};
if (f == 0.0)
return true;
while (true) {
// If f is in ]-1.0; 1.0[, multiply it by 2 and restart.
try {
if (pos0[(int) f]) {
f *= 2.0;
continue;
}
} catch (Exception e) {
}
// If f is in ]-2.0; -1.0] U [1.0; 2.0[, return the proper answer.
try {
return posn[(int) ((f+1.5)/2)];
} catch (Exception e) {
}
// f is outside ]-2.0; 2.0[, divide by 2 and restart.
f /= 2.0;
}
}
static void check(double f)
{
System.out.println(f + " -> " + positive(f));
}
public static void main(String args[])
{
for (double i = -10.0; i <= 10.0; i++)
check(i);
check(-1e24);
check(-1e-24);
check(1e-24);
check(1e24);
}
输出结果为:
-10.0 -> false
-9.0 -> false
-8.0 -> false
-7.0 -> false
-6.0 -> false
-5.0 -> false
-4.0 -> false
-3.0 -> false
-2.0 -> false
-1.0 -> false
0.0 -> true
1.0 -> true
2.0 -> true
3.0 -> true
4.0 -> true
5.0 -> true
6.0 -> true
7.0 -> true
8.0 -> true
9.0 -> true
10.0 -> true
-1.0E24 -> false
-1.0E-24 -> false
1.0E-24 -> true
1.0E24 -> true
答案 29 :(得分:0)
我不知道Java究竟是如何强制数值的,但答案非常简单,如果放入伪代码(我将详细信息留给您):
sign(x) := (x == 0) ? 0 : (x/x)
答案 30 :(得分:-1)
static boolean isNegative(double v) {
return new Double(v).toString().startsWith("-");
}
答案 31 :(得分:-2)
if(antennaHeight.compareTo(Double.valueOf(0))>=0)
在上面的代码中,
antennaHeight.compareTo(Double.valueOf(0))
---这将返回int,将其与0进行比较得出解决方案。
答案 32 :(得分:-3)
if (v < 0) System.out.println("negative"); else System.out.println("positive");