Arithmetic problems with java longs - java

I have two equations: x * x - D * y * y = 1 and x = sqrt(1 + D * y * y).
Both are algebraic manipulations of the other.
Given D, I need to solve for the smallest integer value of x so that y is also an integer. I loop through possible y values, plug them into the second equation and test if x is an integer. If it is, I return x.
The problem I have is when x, y, and D are plugged into the 1st equation, it does not equal 1.
These are some problematic values:
1. x=335159612 y=42912791 D=61
2. x=372326272 y=35662389 D=109
My intuition is that java's Math.sqrt method does not calculate such a small decimal, however BigDecimal does not have a square root method.
Is my math just wrong? If not, what can I do to accurately calculate x and y?
Edit: Here is the root of the problem along with the method that tests if a double is a a natural number.
public static void main(String[] args){
long x = 335159612, D = 61, y = 42912791;
System.out.println(Math.sqrt(D * y * y + 2)); // 3.35159612E8
System.out.println(x * x - D * y * y); // 3
}
public static boolean isNatural(double d){
return d == (int)d;
}

Be careful with precisions in 'double'.
As per IEEE 754-1985 the double precision provides 16 digits (15,9 to be absolutely precise).
E.g.
a) SQRT(112331965515990542) is
335159611.99999999701634694576505237017910
Which, when converted into double, gives 3.3515961199999999E8
b) SQRT(112331965515990543)
335159611.99999999850817347288252618840968
Which, when converted into double, gives 3.3515961199999999E8.
So, as per IEEE 754-1985 definition, those values are equal.
Apparently, any further logical/mathematical checks will be, generally speaking, inaccurate.
To overcome this limitation I recommend BigMath package from www.javasoft.ch
import ch.javasoft.math.BigMath;
import java.math.BigDecimal;
class Tester {
public static void main(String[] args) {
long D = 61L, y = 42912791L;
double a = Math.sqrt(D * y * y + 1);
double b = Math.sqrt(D * y * y + 2);
System.out.println(a);
System.out.println(b);
System.out.println(a == b);
BigDecimal bda = BigMath.sqrt(new BigDecimal(D * y * y + 1), 32);
BigDecimal bdb = BigMath.sqrt(new BigDecimal(D * y * y + 2), 32);
System.out.println(bda.toString());
System.out.println(bdb.toString());
System.out.println(bda.equals(bdb));
}
}
Result:
3.35159612E8
3.35159612E8
true
335159611.99999999701634694576505237017910
335159611.99999999850817347288252618840968
false
P.s. to completely ruin your faith in standard Java maths try this:
System.out.println(0.9200000000000002);
System.out.println(0.9200000000000001);
You will see:
0.9200000000000002
0.9200000000000002

This kind of Diophantine's equations is known as Pell's equations.
Wiki.
Mathworld.
Both links contain clues - how to solve this equation using continued fractions.
I think it would be nice to apply some math instead of brutforce/

If sqrt is the issue, use the first equation instead. If x is an integer, x^2 will also be an integer; if x is not an integer, then x^2 would also not be an integer, as long as you are using BigDecimals with sufficient scale for your math and not doubles.

Related

How to calculate the percentage increasment in java

I want to calculate the increase of percentage of a variable from type int while using another variable from type int for the percentage (50 percent).
thanks in advance for anyone who is willing to help.
`
int a = 3;
int percentage = 3 / 2;
// here I get 3 instead of 4 which is the required answer.
a = a * percentage;
System.out.println(a);
// but here I get the required answer normally.
a = 3;
a = a * 3 / 2;
System.out.println(a);
`
"Percentage" is just a weird of "this value that generally is between 0 and 1 should be rendered by multiplying by 100 and adding a % symbol afterwards". In other words, it's purely a way to display a thing. 50% means 0.5.
int cannot represent 0.5. double sort of can (double and float aren't perfectly accurate). In addition / is integer division if both the left and right side are ints. So, we need to do a few things:
int a = 3;
double b = 1.0 * 3 / 2; // without that 1.0 *, it wouldn't work
System.out.println(b); // prints "1.5"
double c = a * b;
System.out.println(c); // prints 4.5.
int d = ((int) (a * b) + 0.1);
System.out.println(d); // prints 4
Because doubles aren't entirely accurate, and (int) rounds down, adding a small delta (here, 0.1) is a good idea. Otherwise various values will surprise you and go wrong (say, your math ends up at 3.99999999, solely because double is not perfectly accurate, then casting that to int gets you a 3).

How to resolve 'cannot find symbol' errors?

I am trying to solve a complicated mathematical expression using Java on Netbeans, however I have two problems: "cannot find symbol (variable)", and the result I get is always 'NaN'.
But when I tried 'double x = 0;' instead of 'double x;' my code works but the answer I get is always 'NaN'. I also tried initializing the variable on scan 'double x = scan.nextDouble();' but it doesn't work either.
Then I realized the pattern that most of the code I type that involves complicated math, needs to have '= 0;' for the variables to be found by the compiler.
So my real question is, what is the difference between 'double x = 0;' and 'double x;' Why does the former work in mathematical expressions, but the latter can't be detected by the compiler?
Unnecessary Information Below
//The code I made for my homework
double ans, num, den, x, y;
//double x = 0;
//double y = 0;
//variable x and y might not have been initialized
num = Math.cbrt( ((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) )) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = num / den;
System.out.print("x: ");
x = scan.nextDouble();
System.out.print("y: ");
y = scan.nextDouble();
System.out.println("\n The answer is " + ans);
I have the mathematical expression of ((\root(3)((2x^(4)y+2xy^(4)) )))/(4xy^(2x+2y))
I expect the output of
x: 2
y: 3
The answer is 0.096157...
Instead, I get the result of 'variable x and y might not have been initialized' and on another scenario I get the result of 'The answer is NaN'. I'm thinking if I can use variables for each term to solve it.
EDIT: I SUCCESSFULLY MADE THE DIVISION OF THE 'DOUBLES'
by removing the 'double x = 0;', I eliminated the possibility of
'NaN'. Instead, I declare and assign values to variables at the same time.
System.out.print("x: ");
double x = scan.nextDouble();
System.out.print("y: ");
double y = scan.nextDouble();
//preparation
//double term1, term2, term3, term4, term5, term6, exp; //x, y;
//double x = 0;
//double y = 0;
//variable x and y might not have been initialized
//double term1 = (Math.cbrt(2 * Math.pow(x,4) * y));
//double term2 = (Math.cbrt(2 * x * Math.pow(y,4)));
//double term3 = (4 * x);
//double term4 = (2 * x);
//double term5 = (2 * y);
// double exp = term4 + term5;
//double term6 = (Math.pow(y,exp));
//double num = (Math.cbrt((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y, 4))));
//double den = term3 * term6;
double num = (2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) );
double den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
double ans = Math.cbrt(num / den);
System.out.println("\n The answer is " + ans);
Local variables must be given a value before they are referred to. Since your code executes from top to bottom, the calculations will be done before x and y are initialised to the user input values. This is why it says "variable might not be initialised" in your calculations.
Your misconception might be thinking that these lines define some kind of a "relationship" between x, y, num, den:
num = Math.cbrt( ((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) )) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = num / den;
But they actually don't. They simply do the calculations, and set the variable on the left hand side to the result. However, at this point, the values of x and y are not known yet, because the x = ... and y = ... lines haven't run yet.
What if you add double x = 0 and double y = 0 at the top? That solves the compiler error. The calculation can now be carried out, but it will use the x=0 and y=0. That's all the information it has got at that moment, as the lines where you get user input has not been run yet.
What you should do is to move the lines that read the user input before the calculations:
System.out.print("x: ");
x = scan.nextDouble();
System.out.print("y: ");
y = scan.nextDouble();
num = Math.cbrt( ((2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) )) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = num / den;
System.out.println("\n The answer is " + ans);
Also, to get the expected output of 0.096157..., you need the cube root to apply to the whole fraction, not just the numerator:
num = (2 * Math.pow(x,4) * y) + (2 * x * Math.pow(y,4) );
den = (4 * x * Math.pow(y, ((2 * x) + (2 * y))));
ans = Math.cbrt(num / den);
So my real question is, what is the difference between double x = 0; and double x;
The former declares x and gives it an initial value.
The latter declares x and does not give it an initial value. You can give x a value later, but you must do this for all paths that lead to any use of the variable. For example:
double x;
if (Math.pow(2, 2) >= 0.0) {
x = 0.0;
} else {
x = 1.0;
}
System.out.println(x); // OK
versus
double x;
if (Math.pow(2, 2) >= 0.0) {
x = 0.0;
}
System.out.println(x); // ERROR
The latter is a compilation error because there is a possible path through the code where x may be used before it has been initialized.
Now anyone with highschool maths knowledge can tell you that the square of an integer will always be greater or equal to zero, and therefore the else branch will never be taken. However the Java compiler doesn't know this, and will give you a compilation error. (Indeed, it is not permitted to not give you a compilation error. I won't go into the details: they are in the JLS if you care.)
Why does the former work in mathematical expressions, but the latter can't be detected by the compiler?
Now that is an interesting question.
The answer is that = has a fundamentally different meaning in programming languages and mathematical equations.
In a programming language like Java, a = b; means "assign (set) the current value of a to the current value of b".
In an mathematical equation a = b means "for all places where these a and b variables are used, the value of a is equal to the value of b.". It is basically a constraint on the possible values of a and b.
Another way to think about this is that in mathematics, a variable in an equation represents a set of possible values. The equation constrains the set of values; e.g. a = sqrt(4) is equivalent to saying that a denotes {x | x * x == 4} which is the same as the set {-2, +2}.
Now mathematics does have cases where the notation is erroneous. For example a = a + 1 is equivalent to saying that a denotes {x | x == x + 1} ... which is the empty set.
(The notation I used above is not what classical mathematicians and formal methods people would normally use. Unfortunately, it is rather difficult to explain this unless you have taken some University level Mathematics subjects / units. Or a formal methods units in a Computer Science course.)
Finally, here are so generic Q&A's that address your other compilation and runtime errors:
What does a "Cannot find symbol" compilation error mean?
Variable might not have been initialized error
In Java, what does NaN mean?
Local variables including primitives do not have default values assigned and need to be initialized explicitly.
You have to set initial values for x and y, else the compiler protests.
Why must local variables, including primitives, always be initialized in Java?

Java Double convert to Int round

I want to convert a double value to int when and only when 2 numbers after the dot are 0.
Example
double x = 25.001
You can use this :
double x = 25.001;
int i = (int) x;
System.out.println(x);//Input
if (x - i <= 0.01) {
x = (int) x;
}
System.out.println(x);//Output
RESULT
Input Output
25.001 25.0
25.011 25.011
If you want to use a second variable you can use :
int y = 0;
if (x - i <= 0.01) {
y = (int) x;
}
Note
But note, in case your input is not correct, you will always get 0, i like the first solution it is good then the second.
if(x-Integer.parseInt(x)>=0.001)
//Convert here
That rounded number you then cannot store in a double, as a double is always an approximation of a real value - of a series of a (negative) power of 2.
So you should go for BigDecimal as many do that want to do financial software.
If you did something like:
double adjustWhenCloseToInt(double x) {
long n = Math.round(x); // Could overflow for large doubles
if (Math.abs(x - n) < 0.01) {
x = n;
}
return x;
}
A simple
x = adjustWhenCloseToInt(x);
System.out.print(x);
Could still print 0.00000001 or such.
The solution there is
System.out.printf("%.2f", x);
Or better use a localized MessageFormat (thousand separators and such).
As floating point always bears rounding errors, I would in general go for BigDecimal, though it is a circumstantial class to use. Take care to use String constructors:
new BigDecimal("3.99");
As they then can maintain a precision of 2.

Poisson Distrubtion using Normal Approximation in Java

If you are unsure of what "Poisson Distrubtion using Normal Approximation" means, follow this link and check the texts inside the yellow box.
https://onlinecourses.science.psu.edu/stat414/node/180
Here, is the simple snapshot of the math from the link.
P(Y≥9) = P(Y>8.5) = P(Z>(8.5−6.5)/√6.5) = P(Z>0.78)= 0.218
So to get the value in .218, we use Simpson's integration rule which
integrates the function(Implemented in method named "f" from code below) from "negative
infinity" to the value that equals to this >> "((8.5−6.5)/√6.5))"
R successfully gives the correct output. But in Java when i implemented the code
below copied from "http://introcs.cs.princeton.edu/java/93integration/SimpsonsRule.java.html"
I get "0.28360853976343986" which should have been ".218" Is it any how because of the negative infinity value I am using, which is "Double.MIN_VALUE"
This is the code in Java. See at the very end for my INPUTS in the main method.
* Standard normal distribution density function.
* Replace with any sufficiently smooth function.
**********************************************************************/
public static double f(double x) {
return Math.exp(- x * x / 2) / Math.sqrt(2 * Math.PI);
}
/**********************************************************************
* Integrate f from a to b using Simpson's rule.
* Increase N for more precision.
**********************************************************************/
public static double integrate(double a, double b) {
int N = 10000; // precision parameter
double h = (b - a) / (N - 1); // step size
// 1/3 terms
double sum = 1.0 / 3.0 * (f(a) + f(b));
// 4/3 terms
for (int i = 1; i < N - 1; i += 2) {
double x = a + h * i;
sum += 4.0 / 3.0 * f(x);
}
// 2/3 terms
for (int i = 2; i < N - 1; i += 2) {
double x = a + h * i;
sum += 2.0 / 3.0 * f(x);
}
return sum * h;
}
// sample client program
public static void main(String[] args) {
double z = (8.5-6.5)/Math.sqrt(6.5);
double a = Double.MIN_VALUE;
double b = z;
System.out.println(integrate(a, b));
}
Anybody has any ideas? I tried using Apache math's "PoissonDistribution" class's method "normalApproximateProbability(int x)". But the problem is this method takes an "int".
Anyone has any better ideas on how do I get the correct output or any other code. I have used another library for simpson too but I get the same output.
I need this to be done in Java.
I tried to test the code by writing another method that implements Simpson's 3/8 rule instead of your integrate function. It gave the same result as the one you obtained at first time. So i think the difference arises most probably from rounding errors.

Why is my math with Doubles coming out wrong?

This is how I am creating q
Double q = ((r * (i/5)) + y);
at this point the values of the other variables are
r = 3.470694142992069E-5
i = 1
y = -116.30237535361584
but
q = -116.30237535361584
is there something wrong with this math? ( Java )
q should be -116.30236841222755
i and 5 are both integers, so the (i/5) portion evaluates to an integer (0). That negates the multiplication by r, so you're left with only the value for y.
Try
Double q = ((r * ((double)i/5)) + y);
Here's the complete code.
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
double r = 3.470694142992069E-5;
int i = 1;
double y = -116.30237535361584;
Double q = ((r * ((double)i/5)) + y);
System.out.println(q);
}
}
Output:
-116.30236841222755
If i is an integer (which seems to be the case), then the i/5 expression will perform integer math resulting in zero.
i is not a double. Integer division floors. Anything times 0 is 0.
maybe you can try
Double q = ((r * i/5.0) + y);
Floating point values are notoriously imprecise. The difference you're showing can be expected for double arithmetic. If you really need the extra precision, jquantity is an open source Java library for precise math.

Categories

Resources