Java 如何确定一个数字是正数还是负数?
我在一次采访中被问到,如何确定一个数字是正还是负。规则是,我们不应该使用关系运算符,如Java 如何确定一个数字是正数还是负数?,java,numbers,Java,Numbers,我在一次采访中被问到,如何确定一个数字是正还是负。规则是,我们不应该使用关系运算符,如、内置java函数(如子字符串、indexOf、charAt和startsWith),不使用正则表达式或API 我做了一些家庭作业,下面给出了代码,但它只适用于整数类型。但是他们要求我编写一个通用代码,它适用于float、double和long // This might not be better way!! S.O.P ((( number >> 31 ) & 1) == 1 ?
、内置java函数(如子字符串
、indexOf
、charAt
和startsWith
),不使用正则表达式或API
我做了一些家庭作业,下面给出了代码,但它只适用于整数类型。但是他们要求我编写一个通用代码,它适用于float
、double
和long
// This might not be better way!!
S.O.P ((( number >> 31 ) & 1) == 1 ? "- ve number " : "+ve number );
您有什么想法吗?使用条件语句编写,然后查看生成的汇编代码。未经测试,但说明了我的想法:
boolean IsNegative<T>(T v) {
return (v & ((T)-1));
}
布尔值为负(tV){
返回(v&(T)-1);
}
以下是一种可怕的方法,会让你在任何工作中被解雇
这取决于您是否获得堆栈溢出异常[或Java如何调用它]。。。它只适用于不偏离0的正数
负数是可以的,因为您将溢出为正数,然后最终会得到堆栈溢出异常[这将返回false,或“yes,it is Negative”]
Boolean正(ta)
{
如果(a==0),则返回true;
其他的
{
尝试
{
返回为正(a-1);
}捕获(StackOverflowException e)
{
return false;//它一直在下面,最后变成了kaboom
}
}
}
您可以执行以下操作:
((long) (num * 1E308 * 1E308) >> 63) == 0 ? "+ve" : "-ve"
这里的主要思想是,我们将其转换为long并检查最高有效位的值。由于-1和0之间的double/float在转换为long时将舍入为零,因此我们将乘以大的double,这样负的float/double将小于-1。需要两次乘法,因为存在(虽然它实际上不需要那么大)
比如:
long val1 = ...;
double val2 = ...;
float val3 = ...;
int val4 = ...;
sign((long) valN);
从double/float/integer到long的转换应该保留符号,如果不是实际值…这怎么办
return ((num + "").charAt(0) == '-');
这只适用于除[0..2]之外的所有对象
boolean isPositive = (n % (n - 1)) * n == n;
您可以制作这样的更好的解决方案(除[0..1]外都适用)
通过使用类似于2^m(m整数)的值更改0.5部分,可以获得更好的精度:
对我来说,这似乎是任意的,因为我不知道你将如何获得任何类型的数字,但是检查Abs(数字)怎么样号码?也许&&number!=0整数是平凡的;这你已经知道了。深层次的问题是如何处理浮点值。在这一点上,您必须更多地了解浮点值实际上是如何工作的
关键是,它可以让您获得数字的IEEE表示形式。(该方法实际上是一种直接隐藏的方法,具有处理NaN值的一点魔力。)一旦将double转换为long,您就可以使用0x80000000000000L作为掩码来选择符号位;如果为零,则值为正;如果为一,则值为负。为什么不求出数字的平方根?如果它是负数,java将抛出一个错误,我们将处理它
try {
d = Math.sqrt(THE_NUMBER);
}
catch ( ArithmeticException e ) {
console.putln("Number is negative.");
}
我还能想到一个选择
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;
}
private静态布尔值isPositive(Object numberObject){
Long number=Long.valueOf(numberObject.toString());
返回Math.sqrt((number*number))!=number;
}
私有静态布尔值isPositive(对象编号对象){
Long number=Long.valueOf(numberObject.toString());
long SIGNED LEFTSHIFTEREDNUMBER=number>>1;//无符号右移位
返回unsignedRightShifterNumber==number;
}
如果答案有效
boolean IsNegative(char[] v) throws NullPointerException, ArrayIndexOutOfBoundException
{
return v[0]=='-';
}
好吧,利用casting(因为我们不关心实际值是多少)也许下面的方法可以奏效。请记住,实际实现并不违反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));
}
}
整数的情况很简单。在你记起无穷大之前,双格法更为棘手
注意:如果考虑双常量“API的一部分”,可以用溢出的表达式替换它们,如“代码> 1E308* 2 < < /P>”。
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");
}
我不知道Java到底是如何强制数值的,但答案很简单,如果放入伪代码(我把细节留给您): 如果您被允许使用“==”,那么您可以利用这样一个事实,即如果数组索引超出范围,将引发异常。代码用于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);
}
这一个大致基于伊兹瓦蒂的答案,但它在logn时间内运行!警告:只适用于整数
Boolean isPositive(int a)
{
if(a == -1) return false;
if(a == 0) return false;
if(a == 1) return true;
return isPositive(a/2);
}
此解决方案不使用条件运算符,但依赖于捕获两个例外 除法错误等于原来是“负数”的数字。或者,该数字最终会从行星上掉下来,如果是正数,则抛出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;
}
}
我认为有一个非常简单的解决方案:
public boolean isPositive(int|float|double|long i){
return (((i-i)==0)? true : false);
}
如果我错了,告诉我!你说
我们不应该使用条件运算符
但这是一个技巧性要求,因为==
也是一个条件运算符。中还内置了一个:
、while
和for
循环。因此,几乎所有人都未能提供满足所有要求的答案
构建一个没有条件运算符的解决方案的唯一方法是使用查找表,而不是其他几个人的解决方案中的一个
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");
}
sign(x) := (x == 0) ? 0 : (x/x)
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
Boolean isPositive(int a)
{
if(a == -1) return false;
if(a == 0) return false;
if(a == 1) return true;
return isPositive(a/2);
}
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;
}
}
public boolean isPositive(int|float|double|long i){
return (((i-i)==0)? true : false);
}
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
}
}
T sign(T x) {
if(x==0) return 0;
return x/Math.abs(x);
}
if (((Double)calcYourDouble()).toString().contains("-"))
doThis();
else doThat();
static <T extends Number> boolean isNegative(T number)
{
return ((number.doubleValue() * Double.POSITIVE_INFINITY) == Double.NEGATIVE_INFINITY);
}
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";
}
private static boolean isNeg(T l) {
return (Math.abs(l-1)>Math.abs(l));
}
public static boolean isNegative(Number number) {
return (Double.doubleToLongBits(number.doubleValue()) & Long.MIN_VALUE) == Long.MIN_VALUE;
}