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.
Related
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 :)
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.
I'm try to see if large numbers are prime or not, number whose length are 11. Here is the code I am using:
private static boolean isPrime(BigInteger eval_number){
for(int i=2;i < eval_number.intValue();i++) {
if(eval_number.intValue() % i==0)
return false;
}
return true;
}
Now the number I'm inspecting in the debugger is eval_number which equals 11235813213. However when I inspect the eval_number.intValue() in the debugger instead of the value being 11235813213 the value is -1649088675. How is this happening? Also what would be a better way in inspecting large numbers to see if they are prime?
The strange value is a result of an overflow. The number held by the BigInteger instance is greater than 2^31-1 (Integer.MAX_VALUE) thus it can't be represented by an int. For the primcheck: BigInteger provides isProbablePrime(int) and there are several other fast (more or less) algorithms that allow to check whether a number is a primnumber with a given failure-rate. If you prefer 100% certainty you can optimize your code by reducing the upper-bounds for numbers to check to sqrt(input) and increasing the step-size by two. Or generate a prim-table, if the algorithm is used several times.
intValue() returns an integer equivalent for the given BigInteger number.
Since you are passing the value 11235813213, which is much larger than Integer.MAX_VALUE(maximum possible value for an int variable), which is 2147483647. So , it resulted in overflowing of the integer.
Also what would be a better way in inspecting large numbers to see if
they are prime?
You should use only BigInteger numbers for finding out large primes. Also, check this question (Determining if a BigInteger is Prime in Java) which I asked a year ago.
As others have said the number you are checking is ouside of the range of int.
You could use a long, but that only delays the problem, it will still fail on numbers beyond long's range.
The solution is to use BigInteger arithmetic :
private static boolean isPrime(BigInteger eval_number) {
for (BigInteger i = BigInteger.valueOf(2); i.compareTo(eval_number) < 0; i = i.add(BigInteger.ONE)) {
if (eval_number.mod(i).equals(BigInteger.ZERO)) {
return false;
}
}
return true;
}
That is just a correction of the inmediate problem your question is about. There are still things to improve there. Checking for being prime can be made more efficient. You don't have to check even numbers except 2 and you only need to check till the square root of the number in question.
You convert BigInteger to 32bit integer. If it is bigger than 2^31, it will return incorrect value. You need to do all the operations over BigInteger instances. I assume that you use BigInteger because of long being insufficient for other cases, but for number you stated as an example would be use of long instead of int sufficient. (long will be enough for numbers up to 2^63).
You have to make all operations with BigInteger, without converting it to int :
private static boolean isPrime(BigInteger eval_number) {
for (BigInteger i = BigInteger.valueOf(2); i.compareTo(eval_number) < 0; i = i.add(BigInteger.ONE)) {
if (eval_number.divideAndRemainder(i)[1].equals(BigInteger.ZERO)) {
System.out.println(i);
return false;
}
}
return true;
}
If you want to check whether a BigInteger is Prime or not you can use java.math.BigInteger.isProbablePrime(int certainty) it will returns true if this BigInteger is probably prime, false if it's definitely composite. If certainty is ≤ 0, true is returned.
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.
Suppose I have a method to calculate combinations of r items from n items:
public static long combi(int n, int r) {
if ( r == n) return 1;
long numr = 1;
for(int i=n; i > (n-r); i--) {
numr *=i;
}
return numr/fact(r);
}
public static long fact(int n) {
long rs = 1;
if(n <2) return 1;
for (int i=2; i<=n; i++) {
rs *=i;
}
return rs;
}
As you can see it involves factorial which can easily overflow the result. For example if I have fact(200) for the foctorial method I get zero. The question is why do I get zero?
Secondly how do I deal with overflow in above context? The method should return largest possible number to fit in long if the result is too big instead of returning wrong answer.
One approach (but this could be wrong) is that if the result exceed some large number for example 1,400,000,000 then return remainder of result modulo
1,400,000,001. Can you explain what this means and how can I do that in Java?
Note that I do not guarantee that above methods are accurate for calculating factorial and combinations. Extra bonus if you can find errors and correct them.
Note that I can only use int or long and if it is unavoidable, can also use double. Other data types are not allowed.
I am not sure who marked this question as homework. This is NOT homework. I wish it was homework and i was back to future, young student at university. But I am old with more than 10 years working as programmer. I just want to practice developing highly optimized solutions in Java. In our times at university, Internet did not even exist. Today's students are lucky that they can even post their homework on site like SO.
Use the multiplicative formula, instead of the factorial formula.
Since its homework, I won't want to just give you a solution. However a hint I will give is that instead of calculating two large numbers and dividing the result, try calculating both together. e.g. calculate the numerator until its about to over flow, then calculate the denominator. In this last step you can chose the divide the numerator instead of multiplying the denominator. This stops both values from getting really large when the ratio of the two is relatively small.
I got this result before an overflow was detected.
combi(61,30) = 232714176627630544 which is 2.52% of Long.MAX_VALUE
The only "bug" I found in your code is not having any overflow detection, since you know its likely to be a problem. ;)
To answer your first question (why did you get zero), the values of fact() as computed by modular arithmetic were such that you hit a result with all 64 bits zero! Change your fact code to this:
public static long fact(int n) {
long rs = 1;
if( n <2) return 1;
for (int i=2; i<=n; i++) {
rs *=i;
System.out.println(rs);
}
return rs;
}
Take a look at the outputs! They are very interesting.
Now onto the second question....
It looks like you want to give exact integer (er, long) answers for values of n and r that fit, and throw an exception if they do not. This is a fair exercise.
To do this properly you should not use factorial at all. The trick is to recognize that C(n,r) can be computed incrementally by adding terms. This can be done using recursion with memoization, or by the multiplicative formula mentioned by Stefan Kendall.
As you accumulate the results into a long variable that you will use for your answer, check the value after each addition to see if it goes negative. When it does, throw an exception. If it stays positive, you can safely return your accumulated result as your answer.
To see why this works consider Pascal's triangle
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
which is generated like so:
C(0,0) = 1 (base case)
C(1,0) = 1 (base case)
C(1,1) = 1 (base case)
C(2,0) = 1 (base case)
C(2,1) = C(1,0) + C(1,1) = 2
C(2,2) = 1 (base case)
C(3,0) = 1 (base case)
C(3,1) = C(2,0) + C(2,1) = 3
C(3,2) = C(2,1) + C(2,2) = 3
...
When computing the value of C(n,r) using memoization, store the results of recursive invocations as you encounter them in a suitable structure such as an array or hashmap. Each value is the sum of two smaller numbers. The numbers start small and are always positive. Whenever you compute a new value (let's call it a subterm) you are adding smaller positive numbers. Recall from your computer organization class that whenever you add two modular positive numbers, there is an overflow if and only if the sum is negative. It only takes one overflow in the whole process for you to know that the C(n,r) you are looking for is too large.
This line of argument could be turned into a nice inductive proof, but that might be for another assignment, and perhaps another StackExchange site.
ADDENDUM
Here is a complete application you can run. (I haven't figured out how to get Java to run on codepad and ideone).
/**
* A demo showing how to do combinations using recursion and memoization, while detecting
* results that cannot fit in 64 bits.
*/
public class CombinationExample {
/**
* Returns the number of combinatios of r things out of n total.
*/
public static long combi(int n, int r) {
long[][] cache = new long[n + 1][n + 1];
if (n < 0 || r > n) {
throw new IllegalArgumentException("Nonsense args");
}
return c(n, r, cache);
}
/**
* Recursive helper for combi.
*/
private static long c(int n, int r, long[][] cache) {
if (r == 0 || r == n) {
return cache[n][r] = 1;
} else if (cache[n][r] != 0) {
return cache[n][r];
} else {
cache[n][r] = c(n-1, r-1, cache) + c(n-1, r, cache);
if (cache[n][r] < 0) {
throw new RuntimeException("Woops too big");
}
return cache[n][r];
}
}
/**
* Prints out a few example invocations.
*/
public static void main(String[] args) {
String[] data = ("0,0,3,1,4,4,5,2,10,0,10,10,10,4,9,7,70,8,295,100," +
"34,88,-2,7,9,-1,90,0,90,1,90,2,90,3,90,8,90,24").split(",");
for (int i = 0; i < data.length; i += 2) {
int n = Integer.valueOf(data[i]);
int r = Integer.valueOf(data[i + 1]);
System.out.printf("C(%d,%d) = ", n, r);
try {
System.out.println(combi(n, r));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Hope it is useful. It's just a quick hack so you might want to clean it up a little.... Also note that a good solution would use proper unit testing, although this code does give nice output.
You can use the java.math.BigInteger class to deal with arbitrarily large numbers.
If you make the return type double, it can handle up to fact(170), but you'll lose some precision because of the nature of double (I don't know why you'd need exact precision for such huge numbers).
For input over 170, the result is infinity
Note that java.lang.Long includes constants for the min and max values for a long.
When you add together two signed 2s-complement positive values of a given size, and the result overflows, the result will be negative. Bit-wise, it will be the same bits you would have gotten with a larger representation, only the high-order bit will be truncated away.
Multiplying is a bit more complicated, unfortunately, since you can overflow by more than one bit.
But you can multiply in parts. Basically you break the to multipliers into low and high halves (or more than that, if you already have an "overflowed" value), perform the four possible multiplications between the four halves, then recombine the results. (It's really just like doing decimal multiplication by hand, but each "digit" is, say, 32 bits.)
You can copy the code from java.math.BigInteger to deal with arbitrarily large numbers. Go ahead and plagiarize.