Comparator with double type - java

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();

Related

Java double incorrect cast to int

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

Implementing involving contains and interval

The method cannot have if or loop. so it returns true if a number is contained in an interval. it works with [1,6]... but how would I fix this so it would work with an open (1,6) or an interval such as [1,6)??'
I want it to be able to return all scenarios with (1,3] (1,3) [1,3) and [1,3], but with no if statements. How could I make one return statement for to be able to return these scenarios
Remove equals sign (=). Like that:
return (n > leftNumber && n < rightNumber);
You can modify for the others situations (such as [1,6) and (1, 6[)
Change your return statement to look like below if you want to work for interval [1,6)
return (n >= leftNum && n < rightNum);
For (1,6), the return statement can be modified as below
return (n > leftNum && n < rightNum);
You'd need a class to define which type of interval you want on each side of the comparison. I would use an enum:
public enum Interval {
CLOSED, OPEN;
}
Then you would redefine the method declaration as:
public boolean contains(double number, Interval left, Interval right)
and redefine the return statement with ternary operators to return the desired boolean.
The only way I can think to do this given your restrictions is to add a level of indirection. Your contains method needs to take some sort of interval calculation:
boolean contains(double number, Interval interval) {
double leftNum = this.getLeftEndPoint();
double rightNum = this.getRightEndPoint();
return interval.check(leftNum, number, rightNum);
}
Then you create the four interval objects you need:
class ClosedInterval implements Interval {
#Override
boolean check(double lowerBound, double value, double upperBound) {
return (lowerBound <= value) && (value <= upperBound);
}
}
class LowerHalfOpenInterval implements Interval {
#Override
boolean check(double lowerBound, double value, double upperBound) {
return (lowerBound < value) && (value <= upperBound);
}
}
etc...
This seems needlessly complex for the problem at hand, though. You could also just define separate methods for each of the various contains variants you want to handle.

Correct implementation of the equals()-Method for fractions

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!

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
}

Categories

Resources