Correct implementation of the equals()-Method for fractions - java

I want that the printn methods give me "Asterix" and "Oberlix" since 3/4 is the same as 6/8.
HashMap hm = new HashMap();
hm.put(new Fraction(3, 4), "Asterix");
hm.put(new Fraction(19, 12), "Oberlix");
System.out.println(hm.get(new Fraction(6, 8)));
System.out.println(hm.get(new Fraction(38, 24)));
So that is how I implemented the equals-Method:
public boolean equals(Object obj) {
boolean isEqual = false;
if(obj instanceof Fraction) {
Fraction frac = (Fraction) obj;
if(((double) this.numerator / (double) this.denumerator) == ((double) frac.numerator / (double) frac.denumerator)) {
isEqual = true;
}
}
return isEqual;
}
Obviously I did something wrong, because that doesn't work and my print method returns "null". My idea was that if I devide the numerator and the denumerator of both fractions, the result must be equal, if the fractions are equal (3/4 is the same as 6/8).
Sorry guys, I guess the mistake must be somehow obvious but I can't find it.

You could do for equals
return denominator * other.numerator == numerator * other.denominator;
But nicer is to make canonical Fraction.
Either in the equals or in the constructor normalize the fraction: 6/8 becoming 3/4.
public class Fraction implements Number {
private final int numerator;
private final int denominator;
public Fraction(int numerator, int denominator) {
if (denominator < 0) {
denominator = -denominator;
numberator = -numerator;
}
int commonFactor = gcd(numerator, denominator);
this.numerator = numerator / commonFactor;
this.denominator = denominator / commonFactor;
}
#Override
public boolean equals(Object other) {
...
Fraction otherFraction = ...
return denominator == otherFraction.denominator
&& numerator == otherFraction.numerator;
}
private static int gcd(int x, int y) {
x = Math.abs(x);
y = Math.abs(y);
...
while (x != y) {
if (x > y) {
x -= y;
} else {
y -= x;
}
}
return x;
}
What is nicer? You can now make a hashCode:
#Override
int hashCode() {
return denominator * 31 + numerator;
}
Floating point is an approximating sum of a limited number of powers of 2.

For a HashMap to work, you need to implement both equals and hashCode. I'll provide a partial answer, for equals only, because I don't have much time.
To compare two fractions without resorting to doubles, just do some simple arithmetic. You have two fractions, a/b and c/d. Assuming the denominators are nonzero:
a/b == c/d
(multiply left and right by b)
a == c/d*b
(multiply left and right by d)
a*d == c*b
So:
public boolean equals(Object obj) {
if (!(obj instanceof Fraction)) {
return false;
}
Fraction other = (Fraction) obj;
return this.numerator * other.denominator == other.numerator * this.denominator;
}
Note that this won't work for very large fractions; they will overflow. Cast to long if you want to deal with these correctly.
For implementing hashCode, you could simplify the fraction using the Euclidean algorithm, then xor the hash codes of the numerator and the denominator.

You should never compare double with == because System.out.println(0.1+0.1+0.1) will not always be 0.3 (for me, it output 0.30000000000000004). Use equals or compare method from Double.
Because you are storing both numerator and denumenator in your class Fraction, you should use a close enough condition with a custom epsilon in your equals method:
public boolean equals(Object obj) {
boolean isEqual = false;
if(obj instanceof Fraction) {
Fraction frac = (Fraction) obj;
if(Math.abs(((double)this.numerator)/this.denumerator) - ((double)frac.numerator)/frac.denumerator) < .00000001/*epsilon*/) {
isEqual = true;
}
}
return isEqual;
}
Also, you will need to override the hashCode method in your class Fraction in order to use HashMap. Since this equals implementation only depend on one value (the result of the fraction) you could use the following :
public int hashCode()
{
return 0;//all Fraction return the same hashCode, which make HashMap call equals each time
//EDIT: the following is WRONG: assuming eps = 0.1, 299/100 is equals to 300/100 but hashCode will be different (2 and 3).
//return this.numerator/this.denumerator ;//since those are int (I guess),
//it will truncate the floating part. So you will just check for the integer part.
}

as the posts from above, the way to your solution is the use of "hasCode()" and not equals().
Here is an option on how you can get the proper hashCode:
#Override
public int hashCode() {
// Calculating with double is troublesome sometimes, so i use BigDecimal here
BigDecimal value = BigDecimal.valueOf(this.numerator).divide(BigDecimal.valueOf(this.denumerator), RoundingMode.HALF_UP);
// after this, i just return the hashCode i would get, if if my parameter was a simple Double Value:
return Double.valueOf(value.doubleValue()).hashCode();
}
hope this helps!

Related

How to compute `ulp`when `Math.ulp` is missing?

I need the ulp for a given double value, but since I am developing for Codename ONE, ulp(double) is not provided. Does anyone know an efficient algorithm to compute ulp in Java? Codename ONE provides just some of the methods in the Math class (javadoc for the CN1 version) and some of the gaps are filled in MathUtil.
As a workaround, I use this (incorrect) code until I find a working replacement:
private double ulp(double y) {
return y/1e15;
}
EDIT: I "rolled my own" and have just posted my code for review. Just in case someone else needs this.
Ok, since I didn't find a working replacement (both Apache Harmony and OpenJDK end up using native methods that are not available on CN1), I wrote my own version (results tested against OpenJDK-version). Just in case anyone needs it.
As for codename One: I submitted a patch to the MathUtil class, so hopefully this will be added sooner or later.
/*
* use a precalculated value for the ulp of Double.MAX_VALUE
*/
private static final double MAX_ULP = 1.9958403095347198E292;
/**
* Returns the size of an ulp (units in the last place) of the argument.
* #param d value whose ulp is to be returned
* #return size of an ulp for the argument
*/
#Override
public double ulp(double d) {
if (Double.isNaN(d)) {
// If the argument is NaN, then the result is NaN.
return Double.NaN;
}
if (Double.isInfinite(d)) {
// If the argument is positive or negative infinity, then the
// result is positive infinity.
return Double.POSITIVE_INFINITY;
}
if (d == 0.0) {
// If the argument is positive or negative zero, then the result is Double.MIN_VALUE.
return Double.MIN_VALUE;
}
d = Math.abs(d);
if (d == Double.MAX_VALUE) {
// If the argument is Double.MAX_VALUE, then the result is equal to 2^971.
return MAX_ULP;
}
return nextAfter(d, Double.MAX_VALUE) - d;
}
#Override
public double copySign(double x, double y) {
return com.codename1.util.MathUtil.copysign(x,y);
}
private boolean isSameSign(double x, double y) {
return copySign(x, y) == x;
}
/**
* Returns the next representable floating point number after the first
* argument in the direction of the second argument.
*
* #param start starting value
* #param direction value indicating which of the neighboring representable
* floating point number to return
* #return The floating-point number next to {#code start} in the
* direction of {#direction}.
*/
#Override
public double nextAfter(final double start, final double direction) {
if (Double.isNaN(start) || Double.isNaN(direction)) {
// If either argument is a NaN, then NaN is returned.
return Double.NaN;
}
if (start == direction) {
// If both arguments compare as equal the second argument is returned.
return direction;
}
final double absStart = Math.abs(start);
final double absDir = Math.abs(direction);
final boolean toZero = !isSameSign(start, direction) || absDir < absStart;
if (toZero) {
// we are reducing the magnitude, going toward zero.
if (absStart == Double.MIN_VALUE) {
return copySign(0.0, start);
}
if (Double.isInfinite(absStart)) {
return copySign(Double.MAX_VALUE, start);
}
return copySign(Double.longBitsToDouble(Double.doubleToLongBits(absStart) - 1L), start);
} else {
// we are increasing the magnitude, toward +-Infinity
if (start == 0.0) {
return copySign(Double.MIN_VALUE, direction);
}
if (absStart == Double.MAX_VALUE) {
return copySign(Double.POSITIVE_INFINITY, start);
}
return copySign(Double.longBitsToDouble(Double.doubleToLongBits(absStart) + 1L), start);
}
}
I'm not sure why your implementation of ULP takes signs and other criteria into account, when ULP returns the absolute value of the difference between the given value and the next floating point number in magnitude.
Here's an example of all you need to do; it's written in C#, but it's close enough to Java to understand.
public static double ULP(double value)
{
// This is actually a constant in the same static class as this method, but
// we put it here for brevity of this example.
const double MaxULP = 1.9958403095347198116563727130368E+292;
if (Double.IsNaN(value))
{
return Double.NaN;
}
else if (Double.IsPositiveInfinity(value) || Double.IsNegativeInfinity(value))
{
return Double.PositiveInfinity;
}
else if (value == 0.0)
{
return Double.Epsilon; // Equivalent of Double.MIN_VALUE in Java; Double.MinValue in C# is the actual minimum value a double can hold.
}
else if (Math.Abs(value) == Double.MaxValue)
{
return MaxULP;
}
// All you need to understand about DoubleInfo is that it's a helper struct
// that provides more functionality than is used here, but in this situation,
// we only use the `Bits` property, which is just the double converted into a
// long.
DoubleInfo info = new DoubleInfo(value);
// This is safe because we already checked for value == Double.MaxValue.
return Math.Abs(BitConverter.Int64BitsToDouble(info.Bits + 1) - value);
}

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
}

Java hashCode for a Point class

I have a simple custom Point class as follows and I would like to know if my hashCode implemention could be improved or if this is the best it's going to get.
public class Point
{
private final int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
#Override
public boolean equals(Object other)
{
if (this == other)
return true;
if (!(other instanceof Point))
return false;
Point otherPoint = (Point) other;
return otherPoint.x == x && otherPoint.y == y;
}
#Override
public int hashCode()
{
return (Integer.toString(x) + "," + Integer.toString(y)).hashCode();
}
}
Please do not use Strings. There's a lot of theory behind this and several implementations (division method, multiplication one, etc...). If you have about a hour you can watch this MIT-Class
This being said, here is what Netbeans 7.1 suggests:
#Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + this.x;
hash = 71 * hash + this.y;
return hash;
}
October 2015 Edit
I started using IntelliJ a while back, I live happier now. This is what its automatic hashCode generation produces. It's a little less verbose. Note the use of prime numbers as well.
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
The manual multiplication of values of all significant member fields as suggested by Gevorg is probably the most efficient and has a good value distribution. However, if you favour readability, there are nice alternatives available either in Java 7...
import java.util.Objects;
...
#Override
public int hashCode() {
return Objects.hash(x, y);
}
... or in the Guava library:
import com.google.common.base.Objects;
....
#Override
public int hashCode() {
return Objects.hashCode(x, y);
}
Both of these varags methods simply delegate to Arrays.hashCode(Object[] a), so there is a slight impact on performance because of the autoboxing of ints and creating an array of object references, but it should be far less significant than using reflection.
And the readability is just great, since you simply see, which fields are used for the hashcode computation and all the multiply and add syntax is just hidden under the hood of Arrays.hashCode(Object[] a):
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
I would recommend using a simpler and more performant method without strings, perhaps Josh Bloch's method from this answer, in your case just:
return 37 * x + y;
EDIT: nybbler is correct. What is actually recommended is:
int result = 373; // Constant can vary, but should be prime
result = 37 * result + x;
result = 37 * result + y;
A really nice way to hash a 2D point into a single integer is to use a number spiral!
http://ulamspiral.com/images/IntegerSpiral.gif
#Override
public int hashCode() {
int ax = Math.abs(x);
int ay = Math.abs(y);
if (ax>ay && x>0) return 4*x*x-3*x+y+1;
if (ax>ay && x<=0) return 4*x*x-x-y+1;
if (ax<=ay && y>0) return 4*y*y-y-x+1;
return 4*y*y-3*y+x+1;
}
While this method requires a few more calculations, there will be no unpredictable collisions. It also has the nice property that points closer to the origin in general will have smaller hash value. (Still can overflow with x or y > sqrt(MAX_VALUE) however)
From the JDK's Point class (inherited from Point2d):
public int hashCode() {
long bits = java.lang.Double.doubleToLongBits(getX());
bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
return (((int) bits) ^ ((int) (bits >> 32)));
}
That looks slightly better than your implementation.
You can have a look into existing Point type classes implementations:
/**
343 * Returns the hashcode for this <code>Point2D</code>.
344 * #return a hash code for this <code>Point2D</code>.
345 */
346 public int hashCode() {
347 long bits = java.lang.Double.doubleToLongBits(getX());
348 bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
349 return (((int) bits) ^ ((int) (bits >> 32)));
350 }
from: http://kickjava.com/src/java/awt/geom/Point2D.java.htm#ixzz1lMCZCCZw
Simple guide for hashCode implementation can be found here
I used to write my own hash and equals functions then I found this : )
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
#Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
of course keep in mind the following:
Because reflection involves types that are dynamically resolved,
certain Java virtual machine optimizations can not be performed.
Consequently, reflective operations have slower performance than their
non-reflective counterparts, and should be avoided in sections of code
which are called frequently in performance-sensitive applications. SRC
By default, Eclipse will use a hashCode() function for your Point class similar to:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + x;
result = prime * result + y;
return result;
}
At the very least, incorporating a prime number into your hashCode algorithm will help with it's "uniqueness".

Comparator with double type

I have written the following code:
public class NewClass2 implements Comparator<Point>
{
public int compare(Point p1, Point p2)
{
return (int)(p1.getY() - p2.getY());
}
}
If I let's say have two double numbers, 3.2 - 3.1, the difference should be 0.1. When I cast the number to an int, however, the difference ends up as 0, which is not correct.
I therefore need compare() to return a double, not an int. The problem is, my getX field is a double. How can I solve this problem?
I suggest you use the builtin method Double.compare(). If you need a range for double values to be equal you can use chcek for that first.
return Double.compare(p1.getY(), p2.gety());
or
if(Math.abs(p1.getY()-p2.getY()) < ERR) return 0;
return Double.compare(p1.getY(), p2.gety());
The problem with using < and > is that NaN will return false in both cases resulting in a possibly inconsistent handling. e.g. NaN is defined as not being equal to anything, even itself however in #suihock's and #Martinho's solutions, if either value is NaN the method will return 0 everytime, implying that NaN is equal to everything.
You don't need to return double.
The Comparator interface is used to establish an ordering for the elements being compared. Having fields that use double is irrelevant to this ordering.
Your code is fine.
Sorry, I was wrong, reading the question again, this is what you need:
public class NewClass2 implements Comparator<Point> {
public int compare(Point p1, Point p2) {
if (p1.getY() < p2.getY()) return -1;
if (p1.getY() > p2.getY()) return 1;
return 0;
}
}
Since Java 1.8 you can also use
Comparator.comparingDouble(p -> p.getY())
The method compare should return an int. It is a number that is either:
Less than zero, if the first value is less than the second;
Equal to zero, if the two values are equal;
Greater than zero, if the first value is greater than the second;
You don't need to return a double. You must return an int to implement the Comparator interface. You just have to return the correct int, according to the rules I outlined above.
You can't simply cast from int, as, like you said, a difference of 0.1 will result in 0. You can simply do this:
public int compare(Point p1, Point p2)
{
double delta= p1.getY() - p2.getY();
if(delta > 0) return 1;
if(delta < 0) return -1;
return 0;
}
But since comparison of floating-point values is always troublesome, you should compare within a certain range (see this question), something like this:
public int compare(Point p1, Point p2)
{
double delta = p1.getY() - p2.getY();
if(delta > 0.00001) return 1;
if(delta < -0.00001) return -1;
return 0;
}
I just want to expand on Peter Lawrey answer on JDK 8, if you do it like this:
public class NewClass2 implements Comparator<Point> {
public int compare(Point p1, Point p2) {
return Double.compare(p1.getY(), p2.gety());
}
}
You could define this comparator using a lambda expression pretty easily
(Point p1,Point p2) -> Double.compare(p1.getY(), p2.gety())
Better yet, you could use a member reference like this:
Double::compare
It is so convinent in Java 8, choose anyone just as you wish:
Comparator<someClass> cp = (a, b) -> Double.compare(a.getScore(), b.getScore());
Comparator<someClass> cp = Comparator.comparing(someClass::getScore);
Comparator<someClass> cp = Comparator.comparingDouble(someClass::getScore);
int compare(Double first, Double second) {
if (Math.abs(first - second) < 1E-6) {
return 0;
} else {
return Double.compare(first, second);
}
}
Use Double.compare(/**double value 1*/, /**double value 2*/); with a new Comparator for your model class double value.
public static List<MyModel> sortByDouble(List<MyModel> modelList) {
Collections.sort(modelList, new Comparator<MyModel>() {
#Override
public int compare(MyModels1, MyModels2) {
double s1Distance = Double.parseDouble(!TextUtils.isEmpty(s1.distance) ? s1.distance : "0");
double s2Distance = Double.parseDouble(!TextUtils.isEmpty(s2.distance) ? s2.distance : "0");
return Double.compare(s1Distance, s2Distance);
}
});
return modelList;
}
Well, you could multiply those double values by an appropriate factor before converting into integer, for eg. in your case since its only one decimal place so 10 would be a good factor;
return (int)(p1.getY()*10 - p2.getY()*10);
Double min = Arrays.stream(myArray).min(Double::compare).get();

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