Quaternion Comparison? - java

Is quaternion comparison possible? I'm writing a Java class of Quaternions and I want to implement the Comparable interface to use the Collections.sort(List<Quaternion>) facility. I'm not expert at math, I really don't understand the things I read about Quaternions. So, can anyone tell me can I override the compareTo method for Quaternions and how?
My class declarition:
public class Quaternion implements Serializable, Comparable<Quaternion> {
private double s; // scalar part
private double i, j, k; // vectorel part
public Quaternion() {
super();
}
public Quaternion(double s, double i, double j, double k) {
super();
this.s = s;
this.i = i;
this.j = j;
this.k = k;
}

You can implement compareTo, by comparing its fields. However, you need to determine what you want the order to be like. AFAIK, there is no standard definition of what comes before or after for complex numbers let alone a quaternion.

You certainly can compare them; whether the comparison is meaningful or not is open to debate. Since a quaternion can represented by four real numbers, you'd just do something like (pseudocode)
if (q1.a != q2.a)
return q1.a - q2.a;
else if (q1.b != q2.b)
return q1.b - q2.b;
else if (q1.c != q2.c)
return q1.c - q2.c;
else
return q1.d - q2.d;
Since the values are real numbers, you might use an epsilon-based comparison, and you need to convert small positive and negative differences into positive and negative integers. But you get the idea.

There is no reason why you can't compare two quaternions. Assuming that you want to compare magnitudes, compute and compare the Quaternion Norms. Your Quaternion class should have a norm (magnitude) method allowing a toCompare to be something like the following:
int compareTo(Quaternion o){
return (int)(this.norm() - o.norm());
}
A better version would be:
int compareTo(Quaternion o){
// return (int)(this.norm() - o.norm());
double tNorm = this.norm;
double oNorm = o.norm;
int retVal = 0;
if (tNorm < oNorm){
retVal = -1;
} else if (tNorm > oNorm){
retVal = 1;
}
return retVal;
}

A quaternion is a kind of 4-dimensional vector.
How do you want to order them? The most reasonable way would be to use the norm.
public int compareTo(Object o) {
if (o instanceOf Quaternion) {
// Compute the difference between the square of the norm
double result = s*s + i*i + j*j + k*k - o.s*o.s - o.i*o.i - o.j*o.j - o.k*o.k;
if (result > 0) { return 1; }
if (result < 0) { return -1; }
return 0;
}
}
Note that using the norm will make quaternions of equal length but pointing in different directions equal, and some algorithms will not be able to distinguish between them. Sorting algorithms may well throw away "duplicates". Just a friendly warning.

Think about quaternions as a tuple (ordered list) of four floating-point numbers. Defining equality is pretty straightforward, but how would you define total order? In other words, how do you want to define greater-than relationship between two four-number sequences?
In fact, there is no common greater-than relationship even between complex numbers and quaternions can be considered as a pair of complex numbers. Easy comparison is only possible in one-dimensional space. Complex numbers are two-dimensional, quaternions - four.

You can, but I don't think you should.
The argument is the same as for complex numbers. Given two quaternions, they are either equal or not, there is no way to say which one is greater than the other. The quaternions form a division algebra, which is not ordered (unlike the field of the real numbers for example). The only (reasonable) way, I can think of, comparing two quaternions is by using the norm.
double norm = Math.sqrt(s*s + i*i + j*j + k*k);
In that case you could define, that a quaternion a is greater than a quaternion b iff the norm of a is greater than the norm of b. But that is definitely not a standard definition. I would be careful in making quaternions or complex numbers comparable. However, it depends on your use case. Just take into account, that there is no standard way of sorting such numbers.
See this google search for some good links about comparing complex numbers. The argument for quaternions is basically the same.
Another way to compare quaternions would be to use a lexicographic order.

There is no mathematical standard ordering for quaternions or for complex numbers.
You may nevertheless want to implement the Comparable interface, for conveniently sorting and for storing them in TreeSet and TreeMap collections.
To make clear that the ordering is arbitrary I'd use the lexicographic combination of the components of the quaternion. This also ensures that the ordering is consistent with equals, and that the algorithms work as desired.
For a more natural ordering, for example one that takes the norm into account, you can always explicitly define a comparator.

Related

Recurrence Relations with Multiparameter Functions

I have been trying to wrap my head around the concept of a recurrence relation and I see how to divide, conquer and combine. What I am failing to understand is how to derive a proper recurrence relation from a multi argument function that deals with an array of values, a lowest index, and a highest index.
More context:
My base case is when the lowest index is equal to the highest index. When that condition is met I return the the element from the lowest index. (Which is also the highest) It is the only element.
My recursive case is when q and p are not equal. Here is the code below:
int maximum(int[] A, int p, int q) {
if (p == q) {
return A[p];
}
int k, l, max1, max2, max3;
k = p + Math.floor((q-p+2)/3);
l = k + Math.floor((q-p+2)/3);
max1 = maximum(A, p, k-1);
max2 = maximum(A, k, l-1);
max3 = maximum(A, l, q);
if (max1 >= max2 && max1 >= max3) {
return max1;
} else if (max2 >= max1 && max2 >= max3) {
return max2;
} else {
return max3;
}
}
I am not sure how I would go about this. From every example I have seen, I should be using n as my input size and the only parameter I am concerned with is my input size for this.
Would someone be able to explain a best approach to solve for just about any algorithm? I feel like this particular type is getting to me because I am used to seeing simpler recursive functions in the explanations behind recurrence relation.
In situations like these, I have seen the input size to the function considered not to be the literal input size (which may remain more or less the same at each recursive call) but the effective size of the data being considered. In your algorithm - much like in merge sort - the effective size of the data being considered does shrink at each recursive call: your high and low indices bound the part of the array you are looking at, so in a sense your effective input size does shrink. So, rather than treat cases such as these as multiple-variable recursions, I would expect a recursion such as T(n) = 3T(n/3) + O(1), or something of that nature.
Now, there are functions where it makes sense to have multiple independent variables... for instance, a function that takes in two arrays and narrows down at different rates, for instance. Graph algorithms often (though not always) treat vertices and edges as independent variables for complexity bounds, as a concrete case. In those cases, the independent variables are thought of as varying truly independently and cannot be meaningfully combined into a single measure of effective size. That is not necessarily the case in your function.

LeetCode 231: Problem in finding whether a given number is Power of 2

I want to find whether a given number is a power of two in a mathematical way, not with a bitwise approach. Here is my code:
private static double logBaseTwo(final double x) {
return Math.log(x) / Math.log(2);
}
private static double roundToNearestHundredThousandth(final double x) {
return Math.round(x * 100000.0) / 100000.0;
}
private static boolean isInteger(final double x) {
return (int)(Math.ceil(x)) == (int)(Math.floor(x));
}
public static boolean isPowerOfTwo(final int n) {
return isInteger(roundToNearestHundredThousandth(logBaseTwo(n)));
}
It incorrectly returns true for certain numbers, such as 524287. Why is that?
Your code fails because you may need more precision than you allow to capture the difference between the logs of BIG_NUMBER and BIG_NUMBER+1
The bitwise way is really best, but if you really want to use only "mathy" operations, then the best you can do is probably:
public static boolean isPowerOfTwo(final int n) {
int exp = (int)Math.round(logBaseTwo(n));
int test = (int)Math.round(Math.pow(2.0,exp));
return test == n;
}
This solution does not require any super-fine precision, and will work fine for all positive ints.
This is truly horrifyingly bad code, and I have no idea what you are trying to do. You seem to be trying to check if the log base 2 of n is an integer. Instead I would write a loop:
while (n>1) {
m = (n/2) * 2
if (n!=m){
return false;
}
n /=2;
}
return true;
The solution seems more complicated than it should be. I don't get the 100000d parts - seems to potentially cause problems when converting to ceiling.
This is the simple solution that works for all cases:
public static boolean isPowerOfTwo(int n) {
return Math.ceil(Math.log(n)/Math.log(2)) == Math.floor(Math.log(n)/Math.log(2));
}
Originally I had a problem using Math.log in my computations. I switched to Math.log10 and the problem went away. Although mathematically, any logB of base B should work, the nature of floating point math can be unpredictable.
Try this.
public static boolean isPowerOfTwo(int n) {
return n > 0 && Integer.highestOneBit(n) == Integer.lowestOneBit(n);
}
If you prefer to use logs you can do it this way.
public static boolean isPowerOfTwo(int n) {
return n > 0 && (Math.log10(n)/Math.log10(2))%1 == 0;
}
doubles and floats have, respectively, 64-bit and 32-bit precision. That means they can hold at the very most 18446744073709551616 unique numbers. That's a lot of numbers, but not an infinite amount of them. At some point (in fact, that point occurs about at 2^52), the 'gap' between any 2 numbers which are part of the 18446744073709551616 representable ones becomes larger than 1.000. Similar rules apply to small numbers. Math.log does double based math.
Secondarily, ints are similarly limited. They can hold up to 4294967296 different numbers. For ints it's much simpler: Ints can hold from -2147483648 up to 2147483647. If you try to add 1 to 2147483647, you get -2147483648 (it silently wraps around). It's quite possible you're running into that with trying to convert such a large number (your double times 10000d) to an int first.
Note that ? true : false (as in the original version of the question) is literally completely useless. the thing to the left of the question mark must be a boolean, and booleans are already true or false, that's their nature.
See the other answers for simpler approaches to this problem. Although, of course, the simplest solution is to simply count bits in the number. If it's precisely 1 bit, it's a power of 2. If it's 0 bits, well, you tell me if you consider '0' a power of 2 :)

How to create a List of fractions?

I need a way of putting a fraction into an ArrayList. I am having problems however because I'm not sure how I could do this in a way that I could later compare them so they can be sorted.
Note: I will be using 4 or more fractions and I'm not too sure how to (if its possible) to use the comparable class to do it for more than 2.
For example:
I need to input 1/1 , 3/4 , 7/4 , 2/8
I then need to sort them (Using the list) from the smallest to the greatest.
Any help is appreciated.
Create a class called Fraction which stores two variables: numerator and denominator.
You can then make an ArrayList of Fractions.
If you'd like to sort them easily, your best bet is to have it implement Comparable.
public class Fraction implements Comparable<Fraction> {
private int x1, x2; // implement get/set
public int compareTo(Fraction o) {
double tmp = Math.abs((double)x1 / x2 - (double)o.x1 / o.x2);
if (tmp < 0) return -1;
if (tmp < 1e-9) return 0;
return 1;
}
}
Now:
ArrayList<Fraction> f;
Collections.sort(f);
You can do it two ways first you can take fractions as float value otherwise make a class representing the fraction value then make another class implement Interface Comparator.And then use Collections to sort.

Implement “intersection” method using java

How can i implement “intersection” method using java by recieve 2 integer parameters and return integer intersection point.
Maybe this could help
Perhaps you mean bitwise intersection, in which case you are looking for the bitwise-and operator (&). If so, you use it like this:
int x = int1 & int2;
If what you want is a function that takes two 'line' objects and returns a coordinate where they intersect, i suggest looking at the formula here
http://en.wikipedia.org/wiki/Line-line_intersection
and doing
func(line a, lineb)
{
x1 = a.coord1.x;
y1 = a.coord1.y;
x2 = a.coord2.x;
y2 = a.coord2.y;
//do math and code here
return line(coord(x1new,y1new),coord(x2new,y2new));
}
If this isn't what you wanted, please refer to Ido's comment :p
If you want to be really lazy why don't you just use the line2d library. http://download.oracle.com/javase/1.4.2/docs/api/java/awt/geom/Line2D.html It can find the intersect and many other things that have to do with a 2d line already built in.
As far as I can see, if you use two integer parameters, all you really need to do is average the two numbers, and that's the midpoint (intersection, I guess?)
int intersect(int a, int b) {
return ((a + b) / 2);
}
Otherwise, if you are looking for bitwise intersection, you would used the bitwise-AND operator - &. Here's an example:
int intersect(int a, int b) {
return (a & b);
}

How to add two java.lang.Numbers?

I have two Numbers. Eg:
Number a = 2;
Number b = 3;
//Following is an error:
Number c = a + b;
Why arithmetic operations are not supported on Numbers? Anyway how would I add these two numbers in java? (Of course I'm getting them from somewhere and I don't know if they are Integer or float etc).
You say you don't know if your numbers are integer or float... when you use the Number class, the compiler also doesn't know if your numbers are integers, floats or some other thing. As a result, the basic math operators like + and - don't work; the computer wouldn't know how to handle the values.
START EDIT
Based on the discussion, I thought an example might help. Computers store floating point numbers as two parts, a coefficient and an exponent. So, in a theoretical system, 001110 might be broken up as 0011 10, or 32 = 9. But positive integers store numbers as binary, so 001110 could also mean 2 + 4 + 8 = 14. When you use the class Number, you're telling the computer you don't know if the number is a float or an int or what, so it knows it has 001110 but it doesn't know if that means 9 or 14 or some other value.
END EDIT
What you can do is make a little assumption and convert to one of the types to do the math. So you could have
Number c = a.intValue() + b.intValue();
which you might as well turn into
Integer c = a.intValue() + b.intValue();
if you're willing to suffer some rounding error, or
Float c = a.floatValue() + b.floatValue();
if you suspect that you're not dealing with integers and are okay with possible minor precision issues. Or, if you'd rather take a small performance blow instead of that error,
BigDecimal c = new BigDecimal(a.floatValue()).add(new BigDecimal(b.floatValue()));
It would also work to make a method to handle the adding for you. Now I do not know the performance impact this will cause but I assume it will be less than using BigDecimal.
public static Number addNumbers(Number a, Number b) {
if(a instanceof Double || b instanceof Double) {
return a.doubleValue() + b.doubleValue();
} else if(a instanceof Float || b instanceof Float) {
return a.floatValue() + b.floatValue();
} else if(a instanceof Long || b instanceof Long) {
return a.longValue() + b.longValue();
} else {
return a.intValue() + b.intValue();
}
}
The only way to correctly add any two types of java.lang.Number is:
Number a = 2f; // Foat
Number b = 3d; // Double
Number c = new BigDecimal( a.toString() ).add( new BigDecimal( b.toString() ) );
This works even for two arguments with a different number-type. It will (should?) not produce any sideeffects like overflows or loosing precision, as far as the toString() of the number-type does not reduce precision.
java.lang.Number is just the superclass of all wrapper classes of primitive types (see java doc). Use the appropriate primitive type (double, int, etc.) for your purpose, or the respective wrapper class (Double, Integer, etc.).
Consider this:
Number a = 1.5; // Actually Java creates a double and boxes it into a Double object
Number b = 1; // Same here for int -> Integer boxed
// What should the result be? If Number would do implicit casts,
// it would behave different from what Java usually does.
Number c = a + b;
// Now that works, and you know at first glance what that code does.
// Nice explicit casts like you usually use in Java.
// The result is of course again a double that is boxed into a Double object
Number d = a.doubleValue() + (double)b.intValue();
Use the following:
Number c = a.intValue() + b.intValue(); // Number is an object and not a primitive data type.
Or:
int a = 2;
int b = 3;
int c = 2 + 3;
I think there are 2 sides to your question.
Why is operator+ not supported on Number?
Because the Java language spec. does not specify this, and there is no operator overloading. There is also not a compile-time natural way to cast the Number to some fundamental type, and there is no natural add to define for some type of operations.
Why are basic arithmic operations not supported on Number?
(Copied from my comment:)
Not all subclasses can implement this in a way you would expect. Especially with the Atomic types it's hard to define a usefull contract for e.g. add.
Also, a method add would be trouble if you try to add a Long to a Short.
If you know the Type of one number but not the other it is possible to do something like
public Double add(Double value, Number increment) {
return value + Double.parseDouble(increment.toString());
}
But it can be messy, so be aware of potential loss of accuracy and NumberFormatExceptions
Number is an abstract class which you cannot make an instance of. Provided you have a correct instance of it, you can get number.longValue() or number.intValue() and add them.
First of all, you should be aware that Number is an abstract class. What happens here is that when you create your 2 and 3, they are interpreted as primitives and a subtype is created (I think an Integer) in that case. Because an Integer is a subtype of Number, you can assign the newly created Integer into a Number reference.
However, a number is just an abstraction. It could be integer, it could be floating point, etc., so the semantics of math operations would be ambiguous.
Number does not provide the classic map operations for two reasons:
First, member methods in Java cannot be operators. It's not C++. At best, they could provide an add()
Second, figuring out what type of operation to do when you have two inputs (e.g., a division of a float by an int) is quite tricky.
So instead, it is your responsibility to make the conversion back to the specific primitive type you are interested in it and apply the mathematical operators.
The best answer would be to make util with double dispatch drilling down to most known types (take a look at Smalltalk addtition implementation)

Categories