How do I check how many digits my answer has? - java

I'm trying to find the most precise value by calling a method many times. How can I check when the nth iteration will give a value of precision 8 digits. My method returns a double each time I call it, but I want to stop calling it when the result has 8 digits of accuracy in it.
For example, if I call the method getValue() 20 times, and on the 20th time it has an answer that has 8 digits, how do I check the answer and stop the code?
My method is too long to post, so a general explanation should suffice.
The Problem is as follows:
Use the power method to calculate the largest eigenvalue of the Leslie matrix A. The iteration of the power method should stop when you get 8 digits of accuracy.The Leslie Matrix Model can be written as
n(k + 1) = An(k), k = 0, 1, 2,... and with some n(0) given.

double is never going to be precise enough in this way. The only way to know the accuracy of your answer is by doing a mathematical analysis of the operation you're doing and stopping when the error is guaranteed to be less than a certain amount.
However, there is a little bit of a trick if you know your analysis is going to converge. You can compare successive values, and see how large the difference is. Here's some pseudocode:
while(true) {
nextValue = computeNextValue(previousValue);
if(Math.abs(previousValue - nextValue) < ERROR_THRESHOLD) {
break;
}
previousValue = nextValue;
}
#user58697 makes a great point in the comments:
Even if the sequence converges, successive difference may stop the process too early. Knowing the convergence rate is vital.
Keep this in mind when writing your program.

Honestly, I do not believe that there is a generic answer. How do you know that the answer 7.9999999 is more precise than 8.0 (which could be 8.00000000000000) ? It probably depends very much on the problem you want to solve, I guess.

You may use the following hack to check the fractional part. Here is the complete code -
public class FractionCheck{
public static void main(String[] args){
int length1 = findFractionLegth(423423.98476527);
int length2 = findFractionLegth(428294.31231);
System.out.println(length1);
System.out.println(length2);
}
public static int findFractionLegth(double number){
String numberStr = Double.toString(number);
String fractionalStr = numberStr.substring(numberStr.indexOf('.')+1);
return fractionalStr.length();
}
}
The findFractionLegth(double number) method calculate the fractional part of a double.

Related

Fixing recursive exponentiation method?

I am currently working on a method to do an exponentiation calculation using recursion. Here is what I have so far:
public static long exponentiation(long x, int n) {
if (n == 0) {
return 1;
} else if (n == 1) {
return x;
// i know this doesn't work since im returning long
} else if (n < 0) {
return (1 / exponentiation(x, -n));
} else {
//do if exponent is even
if (n % 2 == 0) {
return (exponentiation(x * x, n / 2));
} else {
// do if exponent is odd
return x * exponentiation(x, n - 1);
}
}
}
I have two issues. First issue is that I cannot do negative exponent's, this is not a major issue since I am not required to do negative exponents. Second issue, is certain computations give me the wrong answer. For example 2^63 gives me the correct value, but it gives me a negative number. And 2^64 and on just give me 0. Is there anyway for me to fix this? I know that I could just switch the long's to doubleand my method will work perfectly. However, my professor has required us to use long. Thank you for your help!
The maximum value a long can represent is 2^63 -1. So if you calculate 2^63, it is bigger then what a long can hold and wraps around. Long is represented using twos-complement.
Just changing long to double doesn't exactly work. It changes the semantics of the method. Floating-point numbers have limite precision. With a 64-bit floating point number, you can still only represent the same amount of numbers as with a 64-bit integer. They are just distributed differently. a long can represent every whole number bewteen -2^63 and 2^63-1. A double can represent fractions of numbers as well, but at high numbers, it can't even represent every number.
For example, the next double you can represent after 100000000000000000000000000000000000000000000000000 is 100000000000000030000000000000000000000000000000000 - so you are missiong a whopping 30000000000000000000000000000000000 you can not represent with a double.
You are trying to fix something that you shouldn't bother with fixing. Using a long, there is a fixed maximum return value your method may return. Your method should clearly state what happens if it overflows, and you might want to handle such overflows (e.g. using Math#multiplyExactly), but if long is the return value you are supposed to return, then that is what you should be using.
You could hold the result in an array of longs, let's call it result[]. At first, apply the logic to result[0]. But, when that value goes negative,
1) increment result[1] by the excess.
2) now, your logic gets much messier and I'm typing on my phone, so this part is left as an exercise for the reader.
3) When result[1] overflows, start on result[2]...
When you print the result, combine the results, again, logic messy.
I assume this is how BigInteger works (more or less)? I've never looked at that code, you might want to.
But, basically, Polygnone is correct. Without considerable workarounds, there is an upper limit.

Find zero points with recursion

I want to find the zero points of a sine function. The parameter is a interval [a,b]. I have to it similar to binary search.
Implement a function that searches for null points in the sinus function in a interval between a and b. The search-interval[lower limit, upper limit] should be halved until lower limit and upper limit are less then 0.0001 away from each other.
Here is my code:
public class Aufg3 {
public static void main(String[] args) {
System.out.println(zeropoint(5,8));
}
private static double zeropoint(double a, double b){
double middle = (a + b)/2;
if(Math.sin(middle) < 0){
return zeropoint(a,middle);
}else if(Math.sin(middle) > 0){
return zeropoint(middle,b);
}else{
return middle;
}
}
}
It gives me a lot of errors at the line with return zeropoint(middle,b);
In a first step I want to find just the first zero point in the interval.
Any ideas?
Fundamental problems that everybody has overlooked:
we don't always want to return a result (imagine finding the zero points of the sine function between pi/4 and 3pi/4, there aren't any).
in any arbitrary range range there may be several zeros.
Clearly what is needed is a (possibly empty) set of values.
So pseudocode of the function really asked for (not using Java as this is homework):
Set zeropoint(double a, double b)
{
double middle = mid point of a and b;
if a and be less than 0.0001 apart
{
if (sin(a) and sin(b) are on opposite sides of 0)
{
return set containing middle
}
else
{
return empty set
}
}
else
{
return union of zeropoint(a, middle) and zeropoint(middle, b)
}
}
Simply saying "it gives me errors" is not very helpful. What kind of errors? Compile errors or uncaught exceptions at runtime?
For your code, two things stand out as possible problems:
the variable mitte does not appear to be declared anywhere.
you are using > and < to compare reals. While that is ok by itself, it is better to check for 0 using a tolerance instead of relying on < and >, to avoid problems due to floating point precision. For all practical purposes -0.000000000001 is 0.
There might be other problems as well, I just wrote down the ones that jumped out at first glance.
Edit:
Apparently the mitte was due to an error in pasting the code by the OP (and has since been corrected). As other answers have pointed out, the code falls in to infinite recursion. This is because the recursion calls are on the wrong intervals.
One thing to note, the sin function can be monotonically increasing for one choice of a and b, and monotonically decreasing at some other interval. e.g. It is increasing over [0,pi/2] and it is decreasing over [pi/2,3*pi/2]. Thus the recursive calls need to changed according to the original interval the search is being made in. For one interval Math.sin(middle)<0 implies that Math.sin(x)<0 for all x in [a,middle], but for some other interval the opposite is true. This probably why this falls into infinite recursion for the interval that you are trying. I think this works over some other interval where sin is actually decreasing. Try calling your function over [pi/2,3*pi/2].
I'm guessing you are getting stack overflow errors at runtime. The < and > signs are reversed. Also, you should use .0001 and not 0 to compare to.
Edit 1:
Actually, your basic algorithm has issues. What happens if there are more than one zero in the interval? What happens if sin(a) and the sin(mitte) have the same sign? What happens if there are no zeros in the interval?
Edit 2:
Ok, so I did the problem and fundamentally, your solution is problematic; I would try to start over in thinking how to solve it.
The major issue is that there could be multiple zeros in the interval and you are trying to find each of them. Creating a function that returns a type double can only return one solution. So, rather than creating a function to return double, just return void and print out the zeros as you find them.
Another hint: You are supposed to continue searching until a and b are within .0001 of each other. Your final solution will not use .0001 in any other way. (I.e, your check to see if you found a zero should not use the .0001 tolerance and nor will it use 0 exactly. Think about how you will really know if you have found a zero when abs(a-b) is less than .0001.
Did you read the assignment to the end? It says:
The search-interval[lower limit, upper
limit] should be halved until lower
limit and upper limit are less then
0.0001 away from each other.
So you can't expect Math.sin(middle) to return exactly zero because of floating point precision issues. Instead you need to stop the recursion when you reach 0.0001 precision.
My guess is that you're running into a StackOverflowError. This is due to the fact that you're never reaching a base case in your recursion. (Math.sin(middle) may never equal exactly 0!)
Your exercise says
[...] until lower limit and upper limit are less then 0.0001 away from each other.
So, try putting this in top of your method:
double middle = (a + b)/2;
if (b - a < 0.0001)
return middle;
Besides some floating point problems other have mentioned, your algorithm seems to be based on the implicit assumptions that:
sin(a) is positive
sin(b) is negative, and
sin(x) is a decreasing function on the interval [a,b].
I see no basis for these assumptions. When any of them is false I don't expect your algorithm to work. They are all false when a=5 and b=8.
if(Math.sin(mitte) < 0){
Where is mitte declared? Isn't mitte middle?
private static double zeropoint(double a, double b){
double middle = (a + b)/2;
double result = middle;
if (Math.abs(a - b) > 0.0001) {
double sin = Math.sin(middle);
if (Math.abs(sin) < 0.0001) {
result = middle;
} else if (sin > 0) {
result = zeropoint(a, middle);
} else {
result = zeropoint(middle, b);
}
}
return result;
}
something like this i think - just to fix first errors

Why is Java not telling me when I can't use Integer?

For a small project (Problem 10 Project Euler) i tried to sum up all prime numbers below 2 millions. So I used a brute force method and iterated from 0 to 2'000'000 and checked if the number is a prime. If it is I added it to the sum:
private int sum = 0;
private void calculate() {
for (int i = 0; i < 2000000; i++) {
if (i.isPrime()) {
sum = sum + i;
}
}
sysout(sum)
}
The result of this calculation is 1179908154, but this is incorrect. So i changed int to BigInteger and now i get the correct sum 142913828922. Obviously the range of int was overflowed. But why can't Java tell me that? (e.g. by an exception)
Because it's conceivable that you might want it to behave in the traditional Integer fashion. Exceptions are reserved for things that are definitely and irrevocably wrong.
ETA: From the language spec:
"The built-in integer operators do not
indicate overflow or underflow in any
way. The only numeric operators that
can throw an exception (§11) are the
integer divide operator / (§15.17.2)
and the integer remainder operator %
(§15.17.3), which throw an
ArithmeticException if the right-hand
operand is zero."
(http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html)
Besides what Jim says, checking for conditions such as overflow would add a performance penalty to any calculation done with integers, which would make programs that do a lot of calculations a lot slower.
The other reason is that you can do this check yourself very easily and quickly.
if (sum+i < sum) {
throw new AritchmeticException();
}
should do the trick nicely, given that you know i is always positive and less than Integer.MAX_VALUE.
Being aware of Integer.MAX_VALUE is always useful :)
Because our profession values performance over correctness. ;(
Using BigInteger by default, and only reasoning whether it is acceptable, to use long or int if performance is a real problem, would help to avoid such problems.

How do I go about figuring out this complicated recursion algorithm?

I just started Data Structures and Algorithms which is taught in Java. So far I've only learned C++ in my life so I'm still VERY new to using java.
Anyways I have a homework problem I'm a little stuck on:
Write a recursive method that returns the number of 1's in the binary representation of N. Use the fact that this is equal to the number of 1's in the representation of N/2 + 1, if N is odd.
Now i'm not sure how exactly to do this. I already have a function set up that takes an integer and converts it to binary and stores it in a string, yet the rest I'm kinda lost on.
If I can get some guidance, that would really help.
This is what I have so far:
import java.io.*;
public class Homework1Code {
static void prtbinary(String Molly, int size){
if(size <=0){
return;
}
}
public static void main(String[] args) {
int i = 38;
String binstr = Integer.toBinaryString(i);
System.out.println("The Original Decimal Number is: " + binstr);
prtbinary(binstr, binstr.length());
}
}
Thanks
This is not a hard problem to solve. What you need to do is stop writing code and first solve the problem on paper. Then convert your algorithm to code.
Step one: think!
It is very hard to write a recursive method whose return type is void.
The question is about doing arithmetic, so leave the value as an int rather than convering to a string.
Then there are two facts (for non-negative numbers):
if N is odd then the number of ones is the same as in N/2 plus the one remainder;
if N is even then the number of ones is the same as in N/2.
bitCount of 010101 is bitCount of 010101/2 = 01010 plus 1
bitCount of 010100 is bitCount of 010100/2 = 01010
Rinse and repeat until finished (induction).
Just don't look at the source to Integer.bitCount.
first, reduce the problem to the easiest case ...

Is there any square root function more accurate than java.lang.Math.sqrt(double)

I am looking for square root functions (to use in java) that can give square roots upto atleast to 5-6 decimal places accurately. If there is a way to control accuracy of java.lang.Math.sqrt(double) or any external math library, please mention it.
What problem are you trying to solve? I believe java.lang.Math's sqrt is supposed to be accurate to the full double width. Do you need more than this?
Try out the code at this link, which uses Newton's method to compute square roots for large numbers (and gets BigDecimal output) to see if it fits your needs. If not, you can modify it :) .
http://www.merriampark.com/bigsqrt.htm
You can always implement your own using Newton's Method. Then you can make it as accurate as you want (at the cost of CPU of course).
Numerical Recipes in C has code and in-depth discussion. However make sure you check the license before using their code in your product.
You can use this formula to get it to an arbitrary accuracy:
http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number
I doubt that it will be particularly fast though. You'd also need a way to store numbers with larger than type(double) accuracy.
You could roll your own using BigDecimal and a method like Newton-Raphson. That would allow you to specify a precision.
Have a look at Numerical Recipes if you need any inspiration.
Math.sqrt
public static double sqrt(double a)
Returns the correctly rounded positive square root of a double value. Special cases:
If the argument is NaN or less than zero, then the result is NaN.
If the argument is positive infinity, then the result is positive infinity.
If the argument is positive zero or negative zero, then the result is the same as the argument.
Otherwise, the result is the double value closest to the true mathematical square root of the argument value.
Parameters:
a - a value.
Returns:
the positive square root of a. If the argument is NaN or less than zero, the result is NaN.
This question has been answered thoroughly enough already, but here is an experimental way to verify that Math.sqrt is accurate:
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
double max = 0;
for (int i = 0; i < 100; i++) {
double r = random();
double err = abs(pow(sqrt(r), 2) - r) / ulp(r);
if (err > max) max = err;
}
System.out.println(max);
}
}
This prints out 1.0, confirming what the documentation says — that the value returned from sqrt will be within one unit of precision to the exact answer.
public class SquareRoot {
public void sqRoot_Efficient(int n){ //Time Complexity: O(log(n))
for(int i=1;i<=n;i++){
if((n/i)*(n/i) < n){
System.out.println(n/i);
break;
}
}
}
public static void main(String[] args) {
SquareRoot sr=new SquareRoot();
sr.sqRoot_Efficient(27);
}
}
I usually recommend Apache commons as a first place to look for most tasks.. But it appears the commons.math does not include sqrt().

Categories