I am trying to figure out if two lines are intersecting in a planar. I have been trying to use the cross product of vectors but have been getting wrong answers with large numbers. I realized that some of it was down to not having everything as long but even after this change I have still been finding intersections that don't exist. Can anyone notice were I have slipped up. I have been trying to figure out for quite some time.
My code is as followed:
public static boolean intersecting_segments ( Line_Segment A, Line_Segment B)
{
float side_one;, side_two ,side_three, side_four ;
side_one = cross_product( A, B.p) ;
side_two = cross_product( A, B.q) ;
side_three = cross_product( B, A.p) ;
side_four = cross_product( B, A.q) ;
return ( side_one >0 && side_two <0)|| ( side_one <0 && side_two >0) &&
( side_three >0 && side_four <0)|| ( side_three <0 && side_four >0);
}
public static long cross_product ( Line_Segment S, End_point r )
{
return (long)(((long)r.x -(long)S.p.x)*((long)S.q.y-(long)S.p.y)) -(((long)r.y- (long)S.p.y)*((long)S.q.x-(long)S.p.x));
}
You should make the side_XX variables long as well, which will likely fix your problem. If these variables have to have a decimal, use a double instead of a float.
The reason being though the cross_product function returns a long, the variables they are being assigned to (side_one, side_two, etc) are floats. This will force a conversion from long to float, which would lose precision and be inaccurate with large numbers.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
I can't be 100% sure of this without seeing your Line_Segment code, but based on what you've posted here, I'm guessing the x and y fields are ints, which you're casting to longs in your cross_product() method.
If that's the case, then your casts here aren't doing what you think they are: If, for instance you create a Line_Segment called p with an x value that overflows to 50 (i.e. it is 50 more than the max integer value, which means it gets stored as 50), then p.x is 50, and all you do by casting it to long is to make it 50L - it's not going to "undo" the overflow.
You need to change the types on these variables to long so they're stored properly, and lose the casts. (er, you don't technically have to lose the casts, but they're pointless)
Related
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)
Can someone please explain me why this code doesn‘t compile:
boolean r = (boolean) 0;
Why does this one compile?
double z = (float) 2.0_0+0___2;
I don‘t understand the Alphabet in which the numbers after float are written.
The first one doesn't compile because you simply can't cast a number to a boolean. A boolean is true or false.
The second one just uses underscores, which can be used to separate numbers like 2_000_000 for improved readability. In this case they're used to decrease readability, as is the cast to float (a double cast to float and assigned to double doesn't do anything in this particular case).
The latter case seems to be designed for confusion, as there are several pitfalls. If we remove the unnecessary underscores we get 2.00+02 which adds a literal double with an octal 02. This is still basically just 2+2, but if the octal value were 0___10 you'd get a result of z = 10. Then you have the cast to float which could affect the final result, as 64 bits are forced to 32 bits and then back to 64 bits. This could make the end result less precise than without the cast.
In some languages, like PHP or Javascript 0 is falsy, that is, not false, but evaluated as a boolean value, it will be false. In C, 0 is false. These are possible reasons for your expectation. However, in Java you cannot convert a number to a boolean. If you want to have a truey-ish evaluation, you can implement helper methods, like:
public class LooselyTyped {
public boolean toBoolean(int input) {
return input != 0;
}
public boolean toBoolean(Object input) {
return (input != null) && (!input.equals(""));
}
}
and then:
boolean lt = LooselyTyped.toBoolean(yourvariable);
I'm trying to find some Java code to determine if two doubles are nearly equal. I did a lot of Googling and found bits and pieces that I've put together here. Where it starts to escape me is the use of a "relative epsilon". This approach seems like what I'm looking for. I don't want to have to specify the epsilon directly but want to use an epsilon based on the magnitudes of the two arguments. Here is the code I put together, I need a sanity check on it. (P.S. I know just enough math to be dangerous.)
public class MathUtils
{
// http://stackoverflow.com/questions/3728246/what-should-be-the-
// epsilon-value-when-performing-double-value-equal-comparison
// ULP = Unit in Last Place
public static double relativeEpsilon( double a, double b )
{
return Math.max( Math.ulp( a ), Math.ulp( b ) );
}
public static boolean nearlyEqual( double a, double b )
{
return nearlyEqual( a, b, relativeEpsilon( a, b ) );
}
// http://floating-point-gui.de/errors/comparison/
public static boolean nearlyEqual( double a, double b, double epsilon )
{
final double absA = Math.abs( a );
final double absB = Math.abs( b );
final double diff = Math.abs( a - b );
if( a == b )
{
// shortcut, handles infinities
return true;
}
else if( a == 0 || b == 0 || absA + absB < Double.MIN_NORMAL )
{
// a or b is zero or both are extremely close to it
// relative error is less meaningful here
// NOT SURE HOW RELATIVE EPSILON WORKS IN THIS CASE
return diff < ( epsilon * Double.MIN_NORMAL );
}
else
{
// use relative error
return diff / Math.min( ( absA + absB ), Double.MAX_VALUE ) < epsilon;
}
}
}
I would use a library for this, the one I normally use is DoubleMath fro Googles Guava library. https://google.github.io/guava/releases/19.0/api/docs/com/google/common/math/DoubleMath.html
if (DoubleMath.fuzzyEquals(a, b, epsilon)) {
// a and b are equal within the tolerance given
}
there is also a fuzzyCompare.
The usual way to compare 2 floating values a,b is:
if ( Math.abs(a-b) <= epsilon ) do_stuff_if_equal;
else do_stuff_if_different;
where Math.abs() is absolute value. As I do not code in JAVA you need to use double variant if that is not the case. The epsilon is your difference. As mentioned ulp is too small for this. You need to use value that makes sense for the values you are comparing. So how to compute epsilon?
That is a bit tricky and yes it is possible to use magnitude of a,b but that is not robust way because if exponents of a,b are too different you can obtain false positives easily. Instead you should use a meaning-full value. For example if you are comparing position coordinates then the epsilon should be fraction of min detail or minimal distance you consider as the same point. For angles some minimal angle that is small enough like 1e-6 deg but the value depends on ranges and accuracy you work with. For normalized <-1,1> ranges I usually use 1e-10 or 1e-30.
As you can see the epsilon depends mostly on target accuracy and magnitude and change very from case to case so creating some uniform way (to get rid of epsilon like you want) is not safe and only would lead to head aches later on.
To ease up this I usually define a _zero constant or variable (in case of computational classes) that can be changed. Set it on default to value that is good enough for most cases and if cause problems at some point I know I can easily change it ...
If you want to do it your way anyway (ignoring above text) then you can do this:
if (Math.abs(a)>=Math.abs(b)) epsilon=1e-30*Math.abs(b);
else epsilon=1e-30*Math.abs(a);
but as I said this may lead to wrong results. If you persist on using ulp then I would use Min instead of Max.
You can use the class org.apache.commons.math3.util.Precision from the Apache Commons Math. Example:
if (Precision.equals(sum, price, 0.009)) {
// arguments are equal or within the range of allowed error (inclusive)
}
I'm using Heron's formula to find the area of a triangle. Given sides a, b, and c, A = √(s(s-a)(s-b)(s-c)) where s is the semiperimeter (a+b+c)/2. This formula should work perfectly, but I noticed that Math.pow() and Math.sqrt() give different results. Why does this happen and how can I fix it?
I wrote two methods that find the area and determine if it is an integer.
In this first method, I take the square roots and then multiply them:
public static boolean isAreaIntegral(long a, long b, long c)
{
double s = (a+b+c)/2.0;
double area = Math.sqrt(s)*Math.sqrt(s-a)*Math.sqrt(s-b)*Math.sqrt(s-c);
return area%1.0==0.0 && area > 0.0;
}
In this second method, I find the product and then take the square root:
public static boolean isAreaIntegral(long a, long b, long c)
{
double s = (a+b+c)/2.0;
double area = Math.pow(s*(s-a)*(s-b)*(s-c),0.5);
return area%1.0==0.0 && area > 0.0;
}
Can anyone explain why these two methods that are mathematically equivalent give different Values? I'm working on Project Euler Problem 94. My answer comes out to 999990060 the first way and 996784416 the second way. (I know that both answers are very far off the actual)
I would certainly vote for "rounding issues", as you multiply the results of multiple method call in the first method (where every method result gets rounded) compared to the single method call in the second method, where you round only once.
The difference between the answers is larger than I'd expect. Or maybe it isn't. It's late and my mathematical mind crashed a while ago.
I think your issue is with rounding. When you multiply a load of roots together, your answer falls further from the true value.
The second method will be more accurate.
Though, not necessarily as accurate as Euler is asking for.
A calculator is a good bet.
Both methods are problematic. You should in general be very careful when comparing floating point values (that is, also double precision floating point values). Particularly, comparing the result of a computation with == or != is nearly always questionable (and quite often it is just wrong). Comparing two floating point values for "equality" should be done with a method like
private static boolean isEqual(double x, double y)
{
double epsilon = 1e-8;
return Math.abs(x - y) <= epsilon * Math.abs(x);
// see Knuth section 4.2.2 pages 217-218
}
In this case, the floating-point remainder operator will also not have the desired result. Consider the following, classic example
public class PrecisionAgain
{
public static void main(String[] args)
{
double d = 0;
for (int i=0; i<20; i++)
{
d += 0.1;
}
System.out.println(d);
double r = d%1.0;
System.out.println(r);
}
}
Output:
2.0000000000000004
4.440892098500626E-16
In your case, in order to rule out these rounding errors, the return statement could probably (!) something simple like
return (area - Math.round(area) < 1e8);
But in other situations, you should definitely read more about floating point operations. (The site http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html is often recommended, but might be a tough one to start with...)
This still does not really answer your actual question: WHY are the results different? In doubt, the answer is this simple: Because they make different errors (but they both make errors - that's in fact more important here!)
This question already has answers here:
How to test if a double is an integer
(18 answers)
Closed 9 years ago.
Specifically in Java, how can I determine if a double is an integer? To clarify, I want to know how I can determine that the double does not in fact contain any fractions or decimals.
I am concerned essentially with the nature of floating-point numbers. The methods I thought of (and the ones I found via Google) follow basically this format:
double d = 1.0;
if((int)d == d) {
//do stuff
}
else {
// ...
}
I'm certainly no expert on floating-point numbers and how they behave, but I am under the impression that because the double stores only an approximation of the number, the if() conditional will only enter some of the time (perhaps even a majority of the time). But I am looking for a method which is guaranteed to work 100% of the time, regardless of how the double value is stored in the system.
Is this possible? If so, how and why?
double can store an exact representation of certain values, such as small integers and (negative or positive) powers of two.
If it does indeed store an exact integer, then ((int)d == d) works fine. And indeed, for any 32-bit integer i, (int)((double)i) == i since a double can exactly represent it.
Note that for very large numbers (greater than about 2**52 in magnitude), a double will always appear to be an integer, as it will no longer be able to store any fractional part. This has implications if you are trying to cast to a Java long, for instance.
How about
if(d % 1 == 0)
This works because all integers are 0 modulo 1.
Edit To all those who object to this on the grounds of it being slow, I profiled it, and found it to be about 3.5 times slower than casting. Unless this is in a tight loop, I'd say this is a preferable way of working it out, because it's extremely clear what you're testing, and doesn't require any though about the semantics of integer casting.
I profiled it by running time on javac of
class modulo {
public static void main(String[] args) {
long successes = 0;
for(double i = 0.0; i < Integer.MAX_VALUE; i+= 0.125) {
if(i % 1 == 0)
successes++;
}
System.out.println(successes);
}
}
VS
class cast {
public static void main(String[] args) {
long successes = 0;
for(double i = 0.0; i < Integer.MAX_VALUE; i+= 0.125) {
if((int)i == i)
successes++;
}
System.out.println(successes);
}
}
Both printed 2147483647 at the end.
Modulo took 189.99s on my machine - Cast took 54.75s.
if(new BigDecimal(d).scale() <= 0) {
//do stuff
}
Your method of using if((int)d == d) should always work for any 32-bit integer. To make it work up to 64 bits, you can use if((long)d == d, which is effectively the same except that it accounts for larger magnitude numbers. If d is greater than the maximum long value (or less than the minimum), then it is guaranteed to be an exact integer. A function that tests whether d is an integer can then be constructed as follows:
boolean isInteger(double d){
if(d > Long.MAX_VALUE || d < Long.MIN_VALUE){
return true;
} else if((long)d == d){
return true;
} else {
return false;
}
}
If a floating point number is an integer, then it is an exact representation of that integer.
Doubles are a binary fraction with a binary exponent. You cannot be certain that an integer can be exactly represented as a double, especially not if it has been calculated from other values.
Hence the normal way to approach this is to say that it needs to be "sufficiently close" to an integer value, where sufficiently close typically mean "within X %" (where X is rather small).
I.e. if X is 1 then 1.98 and 2.02 would both be considered to be close enough to be 2. If X is 0.01 then it needs to be between 1.9998 and 2.0002 to be close enough.