Java double incorrect cast to int - java

When i try cast double to int. My variable "check" is always equals zero. But if i do it in psvm it works. If i do it in class check is always equals zero. How can i fix this problem? I try use Double and Integer for cast it doesn't work too.
I use java 11 on Ubuntu 18.
public class Round {
public int round (double value) {
return (value > 0) ? roundPositiveNubmer(value) : roundNegativeNumber(value);
}
private int roundPositiveNubmer(double value) {
int result;
double checkD = value * 10 % 10;
int check = (int) checkD;
if (check > 5) {
value++;
result = (int) value;
} else {
result = (int) value;
}
return result;
}
private int roundNegativeNumber(double value) {
int result;
double checkD = value * 10 % 10;
int check = (int) checkD;
if (check > -5 && check < 0) {
value--;
result = (int) value;
} else {
result = (int) value;
}
return result;
}
}
When i try to round 23.6. I've got 23 but must 24.

Your code works nicely in the positive case, as JB Nizet already hinted in a comment.
The trouble is with the negative case. round(-23.6) yields -23, not -24. It is caused by this line:
if (check > -5 && check < 0) {
In the -23.6 case check is -6, which is less than -5. I think you want the simpler:
if (check < -5) {
Now -23.6 is rounded to -24. -23.5 is still rounded to -23. If you wanted -24 in this case too:
if (check <= -5) {
You may also want to consider whether you wanted >= in the positive case.
Or just use Math.round()
Sourabh Bhat is right in the comment too: You are reinventing the wheel. Math.round() already does the job that your rounding method is doing. So if you are coding this as an exercise, fine, you’re learning, that’s always good. For production code you should prefer to use the existing built-in library method instead.
int rounded = Math.toIntExact(Math.round(-23.6));
System.out.println("Rounded: " + rounded);
Rounded: -24

Related

Java: double rounding algorithm

I got curious about a rounding algorithm, because in CS we had to emulate an HP35 without using the Math library. We didn't include a rounding algorithm in our final build, but I wanted to do it anyway.
public class Round {
public static void main(String[] args) {
/*
* Rounds by using modulus subtraction
*/
double a = 1.123599;
// Should you port this to another method, you can take this as a parameter
int b = 5;
double accuracy = Math.pow(10, -b);
double remainder = a % accuracy;
if (remainder >= 5 * accuracy / 10) // Divide by ten is important because remainder is smaller than accuracy
a += accuracy;
a -= remainder;
/*
* Removes round off error done by modulus
*/
String string = Double.toString(a);
int index = string.indexOf('.') + b;
string = string.substring(0, index);
a = Double.parseDouble(string);
System.out.println(a);
}
}
Is this a good algorithm, or are there any better ones? I don't care about the ones defined in the Java API, I just wanted to know how it was done.
[EDIT]
Here's the code I came up with after looking over EJP's answer
public class Round {
public static void main(String[] args) {
double a = -1.1234599;
int b = 5;
boolean negative = a < 0;
if (negative) a = -a;
String string = Double.toString(a);
char array[] = string.toCharArray();
int index = string.indexOf('.') + b;
int i = index;
int value;
if (Character.getNumericValue(array[index +1]) >= 5) {
for (; i > 0; i--) {
value = Character.getNumericValue(array[i]);
if (value != -1) {
++value;
String temp = Integer.toString(value)
array[i] = temp.charAt(temp.length()-1);
if (value <= 9) break;
}
}
}
string = "";
for (int j=0; j < index + 1 ; j++) {
string += array[j];
}
a = Double.parseDouble(string);
if (negative) a =-a;
System.out.println(a);
}
}
Floating-point numbers don't have decimal places. They have binary places, and the two are not commensurable. Any attempt to modify a floating-point variable to have a specific number of decimal places is doomed to failure.
You have to do the rounding to a specified number of decimal places after conversion to a decimal radix.
There are a different ways to round numbers. The RoundingMode documentation for Java (introduced in 1.5) should give you a brief introduction to the different methods people use.
I know you said you don't have access to the Math functions, but the simplest rounding you can do is:
public static double round(double d)
{
return Math.floor(d + 0.5);
}
If you don't want to use any Math functions, you could try something like this:
public static double round(double d)
{
return (long)(d + 0.5);
}
Those two probably behave differently in some situations (negative numbers?).

How to test if a double is an integer

Is it possible to do this?
double variable;
variable = 5;
/* the below should return true, since 5 is an int.
if variable were to equal 5.7, then it would return false. */
if(variable == int) {
//do stuff
}
I know the code probably doesn't go anything like that, but how does it go?
Or you could use the modulo operator:
(d % 1) == 0
if ((variable == Math.floor(variable)) && !Double.isInfinite(variable)) {
// integer type
}
This checks if the rounded-down value of the double is the same as the double.
Your variable could have an int or double value and Math.floor(variable) always has an int value, so if your variable is equal to Math.floor(variable) then it must have an int value.
This also doesn't work if the value of the variable is infinite or negative infinite hence adding 'as long as the variable isn't inifinite' to the condition.
Guava: DoubleMath.isMathematicalInteger. (Disclosure: I wrote it.) Or, if you aren't already importing Guava, x == Math.rint(x) is the fastest way to do it; rint is measurably faster than floor or ceil.
public static boolean isInt(double d)
{
return d == (int) d;
}
Try this way,
public static boolean isInteger(double number){
return Math.ceil(number) == Math.floor(number);
}
for example:
Math.ceil(12.9) = 13; Math.floor(12.9) = 12;
hence 12.9 is not integer, nevertheless
Math.ceil(12.0) = 12; Math.floor(12.0) =12;
hence 12.0 is integer
Here is a good solution:
if (variable == (int)variable) {
//logic
}
Consider:
Double.isFinite (value) && Double.compare (value, StrictMath.rint (value)) == 0
This sticks to core Java and avoids an equality comparison between floating point values (==) which is consdered bad. The isFinite() is necessary as rint() will pass-through infinity values.
Here's a version for Integer and Double:
private static boolean isInteger(Double variable) {
if ( variable.equals(Math.floor(variable)) &&
!Double.isInfinite(variable) &&
!Double.isNaN(variable) &&
variable <= Integer.MAX_VALUE &&
variable >= Integer.MIN_VALUE) {
return true;
} else {
return false;
}
}
To convert Double to Integer:
Integer intVariable = variable.intValue();
Similar to SkonJeet's answer above, but the performance is better (at least in java):
Double zero = 0d;
zero.longValue() == zero.doubleValue()
My simple solution:
private boolean checkIfInt(double value){
return value - Math.floor(value) == 0;
}
public static boolean isInteger(double d) {
// Note that Double.NaN is not equal to anything, even itself.
return (d == Math.floor(d)) && !Double.isInfinite(d);
}
A simple way for doing this could be
double d = 7.88; //sample example
int x=floor(d); //floor of number
int y=ceil(d); //ceil of number
if(x==y) //both floor and ceil will be same for integer number
cout<<"integer number";
else
cout<<"double number";
My solution would be
double variable=the number;
if(variable-(int)variable=0.0){
// do stuff
}
you could try in this way: get the integer value of the double, subtract this from the original double value, define a rounding range and tests if the absolute number of the new double value(without the integer part) is larger or smaller than your defined range. if it is smaller you can intend it it is an integer value. Example:
public final double testRange = 0.2;
public static boolean doubleIsInteger(double d){
int i = (int)d;
double abs = Math.abs(d-i);
return abs <= testRange;
}
If you assign to d the value 33.15 the method return true. To have better results you can assign lower values to testRange (as 0.0002) at your discretion.
Personally, I prefer the simple modulo operation solution in the accepted answer.
Unfortunately, SonarQube doesn't like equality tests with floating points without setting a round precision. So we have tried to find a more compliant solution. Here it is:
if (new BigDecimal(decimalValue).remainder(new BigDecimal(1)).equals(BigDecimal.ZERO)) {
// no decimal places
} else {
// decimal places
}
Remainder(BigDecimal) returns a BigDecimal whose value is (this % divisor). If this one's equal to zero, we know there is no floating point.
Because of % operator cannot apply to BigDecimal and int (i.e. 1) directly, so I am using the following snippet to check if the BigDecimal is an integer:
value.stripTrailingZeros().scale() <= 0
Similar (and probably inferior) to Eric Tan's answer (which checks scale):
double d = 4096.00000;
BigDecimal bd = BigDecimal.valueOf(d);
String s = bd.stripTrailingZeros().toPlainString();
boolean isInteger = s.indexOf(".")==-1;
Here's a solution:
float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
// var is an integer, so do stuff
}

Will a double equal to an integer always cast to that integer?

Will a double equal to an integer always cast to that integer (assuming the double is not one that causes an overflow). Example: Math.ceil() will return a double that is equal to an integer. Assuming no overflow, will it always cast to the same integer that it is supposedly equal to?
If not, how can I round up a double to an int or long?
Since Java types are fixed and Java doubles have a 52 bit mantissa, they can (with ease) represent a 32-bit Java int without rounding.
Yes, it will convert exactly. This is described in Section 5.1.3 of the JLS, which mentions
Otherwise, if the floating-point number is not an infinity, the
floating-point value is rounded to an integer value V, rounding toward
zero using IEEE 754 round-toward-zero mode...
Since your double exactly equals the int, the "rounded" value is just the exact same value, but you can read the spec for details.
All possible int values can be represented by a double without error. The simplest way to round up is to use Math.ceil() e.g.
double d =
long l = (long) Math.ceil(d); // note: could overflow.
Empirically, the answer seems to be yes - note that it also works with i2 = (int) d;.
public static void main(String[] args) {
for (int i = Integer.MIN_VALUE + 1; i < Integer.MAX_VALUE; i++) {
double d = i;
int i2 = (int) Math.ceil(d);
if (i != i2) {
System.out.println("i=" + i + " and i2=" + i2); //Never executed
}
}
}
I believe so, but you might test it yourself:
public static void main(String... args) throws Exception {
int interactions = Integer.MAX_VALUE;
int i = Integer.MIN_VALUE;
double d = Integer.MIN_VALUE;
long init = System.currentTimeMillis();
for (; i < interactions; i++, d++)
if (!(i == (int) Math.ceil(d)))
throw new Exception("something went wrong with i=" + i + " and d=" + d + ", Math.ceil(d)="+Math.ceil(d));
System.out.println("Finished in: "+(System.currentTimeMillis() - init)+"ms");
}

What is the best way to separate double into two parts "integer & fraction" in java

I have tried to separate 5.6 (for example) by the following method:
private static double[] method(double d)
{
int integerPart = 0;
double fractionPart = 0.0;
integerPart = (int) d;
fractionPart = d - integerPart;
return new double[]{integerPart, fractionPart};
}
But what I got is:
[0] = 5.0
[1] = 0.5999999999999996
Do you have any suggestion about doing this without converting the number to string?
Use BigDecimal to do that same calculation. (using doubles has precision problems because of its representation).
Construct it with new BigDecimal(String.valueOf(yourDouble)) (this is still going through string, but the parts are not separated via string manipulation)
use bd.subtract(new BigDecimal(bd.intValue()) to determine the fraction
Here is another solution based on BigDecimal (that does not go through a String).
private static double[] method(double d) {
BigDecimal bd = new BigDecimal(d);
return new double[] { bd.intValue(),
bd.remainder(BigDecimal.ONE).doubleValue() };
}
As you'll note, you still won't get just 0.6 as output for the fractional part. (You can't even store 0.6 in a double!) This is due to the fact that the mathematical, real number, 5.6 is actually not represented by a double exactly as 5.6 but as 5.599999...
You could also do
private static double[] method(double d) {
BigDecimal bd = BigDecimal.valueOf(d);
return new double[] { bd.intValue(),
bd.remainder(BigDecimal.ONE).doubleValue() };
}
which actually does yield [5.0, 0.6].
The BigDecimal.valueOf is in most JDK's (internally) implemented through a call to Double.toString however. But at least the string-related stuff doesn't clutter your code :-)
Good follow-up question in comment:
If it is represented as 5.599999999..., then why Double.toString(5.6) gives exactly "5.6"
The Double.toString method is actually very sophisticated. From the documentation of Double.toString:
[...]
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.
[...]
The code for getting the characters "5.6" boils down to FloatingDecimal.getChars:
private int getChars(char[] result) {
assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
int i = 0;
if (isNegative) { result[0] = '-'; i = 1; }
if (isExceptional) {
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
if (decExponent > 0 && decExponent < 8) {
// print digits.digits.
int charLength = Math.min(nDigits, decExponent);
System.arraycopy(digits, 0, result, i, charLength);
i += charLength;
if (charLength < decExponent) {
charLength = decExponent-charLength;
System.arraycopy(zero, 0, result, i, charLength);
i += charLength;
result[i++] = '.';
result[i++] = '0';
} else {
result[i++] = '.';
if (charLength < nDigits) {
int t = nDigits - charLength;
System.arraycopy(digits, charLength, result, i, t);
i += t;
} else {
result[i++] = '0';
}
}
} else if (decExponent <=0 && decExponent > -3) {
result[i++] = '0';
result[i++] = '.';
if (decExponent != 0) {
System.arraycopy(zero, 0, result, i, -decExponent);
i -= decExponent;
}
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
result[i++] = digits[0];
result[i++] = '.';
if (nDigits > 1) {
System.arraycopy(digits, 1, result, i, nDigits-1);
i += nDigits-1;
} else {
result[i++] = '0';
}
result[i++] = 'E';
int e;
if (decExponent <= 0) {
result[i++] = '-';
e = -decExponent+1;
} else {
e = decExponent-1;
}
// decExponent has 1, 2, or 3, digits
if (e <= 9) {
result[i++] = (char)(e+'0');
} else if (e <= 99) {
result[i++] = (char)(e/10 +'0');
result[i++] = (char)(e%10 + '0');
} else {
result[i++] = (char)(e/100+'0');
e %= 100;
result[i++] = (char)(e/10+'0');
result[i++] = (char)(e%10 + '0');
}
}
}
return i;
}
To see what is going on, take a look at the binary representations of the numbers:
double d = 5.6;
System.err.printf("%016x%n", Double.doubleToLongBits(d));
double[] parts = method(d);
System.err.printf("%016x %016x%n",
Double.doubleToLongBits(parts[0]),
Double.doubleToLongBits(parts[1]));
output:
4016666666666666
4014000000000000 3fe3333333333330
5.6 is 1.4 * 22, but 0.6 is 1.2 * 2-1. Because it has a lower exponent, normalization causes the mantissa to be shifted three bits to the left. The fact that the recurring terms (..66666..) were originally an approximation of the fraction 7/5 has been forgotten, and the missing bits are replaced with zeros.
Given the original double value as input to your method, there is no way to avoid this. To preserve the exact value you would need to use a format that represents the desired value exactly, e.g. Fraction from Apache commons-math. (For this specific example with d=5.6 a BigDecimal would also be able to represent it exactly, but there are other numbers it cannot represent exactly, e.g. 4/3)
poor-man solution (using String)
static double[] sp(double d) {
String str = String.format(Locale.US, "%f", d);
int i = str.indexOf('.');
return new double[] {
Double.parseDouble(str.substring(0, i)),
Double.parseDouble(str.substring(i))
};
}
(Locale so we really get a decimal point)
String doubleAsString = Double.toString(123.456);
String beforeDecimal=doubleAsString.substring(0,doubleAsString.indexOf(".")); //123
String afterDecimal=doubleAsString.substring(doubleAsString.indexOf(".")+1); //456

How to determine if a number is positive or negative?

I was asked in an interview, how to determine whether a number is positive or negative. The rules are that we should not use relational operators such as <, and >, built in java functions (like substring, indexOf, charAt, and startsWith), no regex, or API's.
I did some homework on this and the code is given below, but it only works for integer type. But they asked me to write a generic code that works for float, double, and long.
// This might not be better way!!
S.O.P ((( number >> 31 ) & 1) == 1 ? "- ve number " : "+ve number );
any ideas from your side?
The integer cases are easy. The double case is trickier, until you remember about infinities.
Note: If you consider the double constants "part of the api", you can replace them with overflowing expressions like 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");
}
The following is a terrible approach that would get you fired at any job...
It depends on you getting a Stack Overflow Exception [or whatever Java calls it]... And it would only work for positive numbers that don't deviate from 0 like crazy.
Negative numbers are fine, since you would overflow to positive, and then get a stack overflow exception eventually [which would return false, or "yes, it is negative"]
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
}
}
}
This will only works for everything except [0..2]
boolean isPositive = (n % (n - 1)) * n == n;
You can make a better solution like this (works except for [0..1])
boolean isPositive = ((n % (n - 0.5)) * n) / 0.5 == n;
You can get better precision by changing the 0.5 part with something like 2^m (m integer):
boolean isPositive = ((n % (n - 0.03125)) * n) / 0.03125 == n;
You can do something like this:
((long) (num * 1E308 * 1E308) >> 63) == 0 ? "+ve" : "-ve"
The main idea here is that we cast to a long and check the value of the most significant bit. As a double/float between -1 and 0 will round to zero when cast to a long, we multiply by large doubles so that a negative float/double will be less than -1. Two multiplications are required because of the existence of subnormals (it doesn't really need to be that big though).
What about this?
return ((num + "").charAt(0) == '-');
// Returns 0 if positive, nonzero if negative
public long sign(long value) {
return value & 0x8000000000000000L;
}
Call like:
long val1 = ...;
double val2 = ...;
float val3 = ...;
int val4 = ...;
sign((long) valN);
Casting from double / float / integer to long should preserve the sign, if not the actual value...
You say
we should not use conditional operators
But this is a trick requirement, because == is also a conditional operator. There is also one built into ? :, while, and for loops. So nearly everyone has failed to provide an answer meeting all the requirements.
The only way to build a solution without a conditional operator is to use lookup table vs one of a few other people's solutions that can be boiled down to 0/1 or a character, before a conditional is met.
Here are the answers that I think might work vs a lookup table:
Nabb
Steven Schlansker
Dennis Cheung
Gary Rowe
This solution uses modulus. And yes, it also works for 0.5 (tests are below, in the main method).
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
}
}
This code covers all cases and types:
public static boolean isNegative(Number number) {
return (Double.doubleToLongBits(number.doubleValue()) & Long.MIN_VALUE) == Long.MIN_VALUE;
}
This method accepts any of the wrapper classes (Integer, Long, Float and Double) and thanks to auto-boxing any of the primitive numeric types (int, long, float and double) and simply checks it the high bit, which in all types is the sign bit, is set.
It returns true when passed any of:
any negative int/Integer
any negative long/Long
any negative float/Float
any negative double/Double
Double.NEGATIVE_INFINITY
Float.NEGATIVE_INFINITY
and false otherwise.
Untested, but illustrating my idea:
boolean IsNegative<T>(T v) {
return (v & ((T)-1));
}
It seems arbitrary to me because I don't know how you would get the number as any type, but what about checking Abs(number) != number? Maybe && number != 0
Integers are trivial; this you already know. The deep problem is how to deal with floating-point values. At that point, you've got to know a bit more about how floating point values actually work.
The key is Double.doubleToLongBits(), which lets you get at the IEEE representation of the number. (The method's really a direct cast under the hood, with a bit of magic for dealing with NaN values.) Once a double has been converted to a long, you can just use 0x8000000000000000L as a mask to select the sign bit; if zero, the value is positive, and if one, it's negative.
If it is a valid answer
boolean IsNegative(char[] v) throws NullPointerException, ArrayIndexOutOfBoundException
{
return v[0]=='-';
}
one more option I could think of
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;
}
This one is roughly based on ItzWarty's answer, but it runs in logn time! Caveat: Only works for integers.
Boolean isPositive(int a)
{
if(a == -1) return false;
if(a == 0) return false;
if(a == 1) return true;
return isPositive(a/2);
}
I think there is a very simple solution:
public boolean isPositive(int|float|double|long i){
return (((i-i)==0)? true : false);
}
tell me if I'm wrong!
Try this without the code: (x-SQRT(x^2))/(2*x)
Write it using the conditional then take a look at the assembly code generated.
Why not get the square root of the number? If its negative - java will throw an error and we will handle it.
try {
d = Math.sqrt(THE_NUMBER);
}
catch ( ArithmeticException e ) {
console.putln("Number is negative.");
}
I don't know how exactly Java coerces numeric values, but the answer is pretty simple, if put in pseudocode (I leave the details to you):
sign(x) := (x == 0) ? 0 : (x/x)
If you are allowed to use "==" as seems to be the case, you can do something like that taking advantage of the fact that an exception will be raised if an array index is out of bounds. The code is for double, but you can cast any numeric type to a double (here the eventual loss of precision would not be important at all).
I have added comments to explain the process (bring the value in ]-2.0; -1.0] union [1.0; 2.0[) and a small test driver as well.
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);
}
The output is:
-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
Well, taking advantage of casting (since we don't care what the actual value is) perhaps the following would work. Bear in mind that the actual implementations do not violate the API rules. I've edited this to make the method names a bit more obvious and in light of #chris' comment about the {-1,+1} problem domain. Essentially, this problem does not appear to solvable without recourse to API methods within Float or Double that reference the native bit structure of the float and double primitives.
As everybody else has said: Stupid interview question. 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));
}
}
This solution uses no conditional operators, but relies on catching two excpetions.
A division error equates to the number originally being "negative". Alternatively, the number will eventually fall off the planet and throw a StackOverFlow exception if it is positive.
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;
}
}
What about the following?
T sign(T x) {
if(x==0) return 0;
return x/Math.abs(x);
}
Should work for every type T...
Alternatively, one can define abs(x) as Math.sqrt(x*x),
and if that is also cheating, implement your own square root function...
if (((Double)calcYourDouble()).toString().contains("-"))
doThis();
else doThat();
Combined generics with double API. Guess it's a bit of cheating, but at least we need to write only one method:
static <T extends Number> boolean isNegative(T number)
{
return ((number.doubleValue() * Double.POSITIVE_INFINITY) == Double.NEGATIVE_INFINITY);
}
Two simple solutions. Works also for infinities and numbers -1 <= r <= 1
Will return "positive" for NaNs.
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";
}
There is a function is the math library called signnum.
http://www.tutorialspoint.com/java/lang/math_signum_float.htm
http://www.tutorialspoint.com/java/lang/math_signum_double.htm
It's easy to do this like
private static boolean isNeg(T l) {
return (Math.abs(l-1)>Math.abs(l));
}
static boolean isNegative(double v) {
return new Double(v).toString().startsWith("-");
}

Categories

Resources