So I am attempting to create a Pollard's Rho Factoring Algorithm in Java using the BigInteger class to support very large integers. The code mostly works but cannot find a factor for 4 or 8 (which should be 2). Currently I have capped it to cycle through the algorithm 10,000,000 times and still it can't find 2 as a factor. a is generated randomly (limited between 0 and 1000). Is this just a flaw in the Pollard Rho Algorithm or is there a mistake somewhere in the implementation?
The n being passed is 4
The initial a is calculated as a random the same way in the below code, between 0 and 1000
The sqrt(n) method returns the floor of the square root of n (in this case sqrt(sqrt(4)) = 1
I printed count at the end to make sure it was actually iterating how many times it was supposed to.
private static BigInteger PollardRho (BigInteger a, BigInteger n) {
BigInteger gcd = BigInteger.ZERO;
BigInteger Tort = a;
BigInteger Hare = a;
BigInteger count = BigInteger.ZERO;
BigInteger iterationLim = (sqrt(sqrt(n))).multiply(BigInteger.valueOf(10000000));
while (count.compareTo(iterationLim)!=0)
//makes sure that the algorithm does not surpass (4th root of n)*10000000 iterations.
{
Tort = ((Tort.pow(2)).add(BigInteger.ONE)).mod(n);
//System.out.println("Tort: "+Tort);
Hare = (((Hare.pow(2)).add(BigInteger.ONE).pow(2)).add(BigInteger.ONE)).mod(n);
//System.out.println("Hare: "+Hare);
gcd = (Tort.subtract(Hare)).gcd(n);
//System.out.println("gcd: "+gcd);
if (gcd.compareTo(BigInteger.ONE) != 0 && gcd.compareTo(n) != 0)
{
// System.out.println("took if, gcd = "+gcd);
return gcd;
}
if (gcd.compareTo(n) == 0)
{
a = (BigInteger.valueOf((long) (1000*Math.random())));
Tort = a;
Hare = a;
}
count = count.add(BigInteger.ONE);
}
System.out.println(count);
return n;
}
Pollard's Rho method usually can only split numbers composed of different primes. It fails most of the time for numbers that are prime powers. 4 and 8 are powers of a single prime 2 and therefore unlikely to be split by this method.
The method works by iterating a random function f(x) mod n, in this case f(x) = x^2+1 is used, but other functions work as well. The trick is that f(x) mod p where p is a prime factor of n enters a cycle after a different number of iterations for different primes. So f(x) mod p1 may already be in a cycle, f(x) mod p2 not yet. The gcd calculation is then able to find the factor p1.
It is btw. very easy to check if a number is a proper power of an integer. Just calculate the 2nd, 3rd, 4th, ... root and check if it is an integer.
Related
I want to write a Java program that sums all the integers n^n from 1 through n. I only need the last 10 digits of this number, but the values given for n exceed 800.
I have already written a basic java program to calculate this, and it works fine for n < 16. But it obviously doesn't deal with such large numbers. I am wondering if there is a way to just gather the last 10 digits of a number that would normally overflow a long, and if so, what that method or technique might be.
I have no code to show, just because the code I wrote already is exactly what you'd expect. A for loop that runs i*i while i<=n and a counter that sums each iteration with the one before. It works. I just don't know how to approach the problem for bigger numbers, and need guidance.
Around n=16, the number overflows a long, and returns negative values. Will BigInteger help with this, or is that still too small a data type? Or could someone point me towards a technique for gathering the last 10 digits of a massive number? I could store it in an array and then sum them up if I could just get that far.
Anyhow, I don't expect a finished piece of code, but maybe some suggestions as to how I could look at this problem anew? Some techniques my n00b self is missing?
Thank you!
sums all the integers n^n from 1 through n. I only need the last 10 digits of this number
If you only need last 10 digits, that means you need sum % 10¹⁰.
The sum is 1¹ + 2² + 3³ + ... nⁿ.
According to equivalences rules:
(a + b) % n = [(a % n) + (b % n)] % n
So you need to calculate iⁱ % 10¹⁰, for i=1 to n, sum them, and perform a last modulus on that sum.
According to the modular exponentiation article on Wikipedia, there are efficient ways to calculate aⁱ % m on a computer. You should read the article.
However, as the article also says:
Java's java.math.BigInteger class has a modPow() method to perform modular exponentiation
Combining all that to an efficient implementation in Java that doesn't use excessive amounts of memory:
static BigInteger calc(int n) {
final BigInteger m = BigInteger.valueOf(10_000_000_000L);
BigInteger sum = BigInteger.ZERO;
for (int i = 1; i <= n; i++) {
BigInteger bi = BigInteger.valueOf(i);
sum = sum.add(bi.modPow(bi, m));
}
return sum.mod(m);
}
Or the same using streams:
static BigInteger calc(int n) {
final BigInteger m = BigInteger.valueOf(10).pow(10);
return IntStream.rangeClosed(1, n).mapToObj(BigInteger::valueOf).map(i -> i.modPow(i, m))
.reduce(BigInteger.ZERO, BigInteger::add).mod(m);
}
Test
System.out.println(calc(800)); // prints: 2831493860
BigInteger would be suitable to work with these kinds of numbers. It's quite frankly what it's designed for.
Do note that instances of BigInteger are immutable and any operations you do on one will give you back a new BigInteger instance. You're going to want to store some of your results in variables.
Given a positive integer n, it is asked to find the probability that one can pick two numbersA and B from the set [1...n], such that the GCD of A and B is B. So my approach was to calculate number of pairs such that one is divisible by another. And the answer was expected to be in irreducible fraction form.
EXAMPLE:
1 2 3
OUTPUT:
1/1 3/4 5/9
long n = sc.nextLong();
long sum=0;
for(long i=1;i<=n/2;i++)
sum+=(n/i)-1;
long tot = n*n;
sum+=n;
long bro = hcf(tot,sum);
sum/=bro;
tot/=bro;
System.out.print(sum+"/"+tot);
And my hcf function was:
public static long hcf(long n1,long n2)
{
if (n2!=0)
return hcf(n2, n1%n2);
else
return n1;
}
But the compiler message was time-out. I think there may be some problem with the hcf function or there is a better and efficient method for finding the irreducible fraction. Since it was successful for smaller inputs, I think there is most probably an efficient method for finding the irreducible fraction form. Any suggestions?
Your hcf function is not too slow. Instead, the problem is that you have a for loop which iterates O(n) times, which is quite a lot when n = 10^9. You can get it down to O(sqrt(n)) by only counting cases where B <= sqrt(A). That will give you about half of the cases, because usually exactly one of B and A/B is smaller than sqrt(A). The only exception is you have to account for cases when B * B = A.
I would like to create an integer value between 1 and infinity. I want to have a probability distribution where the smaller the number is, the higher the chance it is generated.
I generate a random value R between 0 and 2.
Take the series
I want to know the smallest m with which my sum is bigger than R.
I need a fast way to determine m. This is would be pretty straightforward if i had R in binary, since m would be equal to the number of 1's my number has in a row from the most significant bit, plus one.
There is an upper limit on the integer this method can generate: integer values have an upper limit and double precision can also only reach so high in the [0;2[ interval. This is irrelevant, however, since it depends on the accuracy of the data representation method.
What would be the fastest way to determine m?
Set up the inequality
R <= 2 - 2**-m
Isolate the term with m
2**-m <= 2 - R
-m <= log2(2-R)
m >= -log2(2-R).
So it looks like you want ceiling(-log2(2-R)). This is basically an exponential distribution with discretization -- the algorithm for an exponential is -ln(1-U)/rate, where U is a Uniform(0,1) and 1/rate is the desired mean.
I think, straightforward solution will be OK as this series converges really fast:
if (r >= 2)
throw new IllegalArgumentException();
double exp2M = 1 / (2 - r);
int x = (int)exp2M;
int ans = 0;
while (x > 0) {
++ans;
x >>= 2;
}
return ans;
I'm trying to solve problem 3 from http://projecteuler.net. However, when I run thing program nothing prints out.
What am I doing wrong?
Problem: What is the largest prime factor of the number 600851475143 ?
public class project_3
{
public boolean prime(long x) // if x is prime return true
{
boolean bool = false;
for(long count=1L; count<x; count++)
{
if( x%count==0 )
{
bool = false;
break;
}
else { bool = true; }
}
return bool;
}
public static void main(String[] args)
{
long ultprime = 0L; // largest prime value
project_3 object = new project_3();
for(long x=1L; x <= 600851475143L; x++)
{
if( object.prime(x)==true )
{
ultprime = ((x>ultprime) ? x : ultprime);
}
}
System.out.println(ultprime);
}
}
Not only does your prime checking function always return false; even if it were functioning properly, your main loop does not seek the input number's factors at all, but rather just the largest prime smaller or equal to it. In pseudocode, your code is equivalent to:
foo(n):
x := 0 ;
foreach d from 1 to n step 1:
if is_prime(d): // always false
x := d
return x // always 0
is_prime(d):
not( d % 1 == 0 ) // always false
But you don't need the prime checking function here at all. The following finds all factors of a number, by trial division:
factors(n):
fs := []
d := 2
while ( d <= n/d ):
if ( n % d == 0 ): { n := n/d ; fs := append(fs,d) }
else: { d := d+1 }
if ( n > 1 ): { fs := append(fs, n) }
return fs
The testing for divisibility is done only up to the square root of the number. Each factor, as it is found, is divided out of the number being factorized, thus further reducing the run time. Factorization of the number in question runs instantly, taking just 1473 iterations.
By construction all the factors thus found are guaranteed to be prime (that's why no prime checking is needed). It is crucial to enumerate the possible divisors in ascending order for this to happen1. Ascending order is also the most efficient, because any given number is more likely to have smaller prime factor than larger one. Enumerating the primes instead of odds, though not necessary, will be more efficient if you have an efficient way of getting those primes, to test divide by.
It is trivial to augment the above to find the largest factor: just implement append as
append(fs,d):
return d
1
because then for any composite divisor d of the original number being factorized, when we'll reach d, we will have already divided its prime factors out of the original number, and so the reduced number will have no common prime factors with it, i.e. d won't divide the reduced number even though it divides the original.
Two things:
1) You are starting count at 1 instead of 2. All integers are divisible by 1.
2) You are running an O(n^2) algorithm against a rather large N (or at least you will be once you fix point #1). The runtime will be quite long.
The whole point of Project Euler is that the most obvious approaches to finding the answer will take so long to compute that they aren't worth running. That way you learn to look for the less obvious, more efficient approaches.
Your approach is technically correct in terms of whether or not it is capable of computing the largest prime of some number. The reason you aren't seeing anything print out is that your algorithm is not capable of solving the problem quickly.
The way you've designed this, it'll take somewhere around 4,000,000 years to finish.
If you replaced the 600851475143 number with say 20 it would be able to finish fairly quickly. But you have the 600 billion number, so it's not that simple.
Here's my implementation of Fermat's little theorem. Does anyone know why it's not working?
Here are the rules I'm following:
Let n be the number to test for primality.
Pick any integer a between 2 and n-1.
compute a^n mod n.
check whether a^n = a mod n.
myCode:
int low = 2;
int high = n -1;
Random rand = new Random();
//Pick any integer a between 2 and n-1.
Double a = (double) (rand.nextInt(high-low) + low);
//compute:a^n = a mod n
Double val = Math.pow(a,n) % n;
//check whether a^n = a mod n
if(a.equals(val)){
return "True";
}else{
return "False";
}
This is a list of primes less than 100000. Whenever I input in any of these numbers, instead of getting 'true', I get 'false'.
The First 100,008 Primes
This is the reason why I believe the code isn't working.
In java, a double only has a limited precision of about 15 to 17 digits. This means that while you can compute the value of Math.pow(a,n), for very large numbers, you have no guarantee you'll get an exact result once the value has more than 15 digits.
With large values of a or n, your computation will exceed that limit. For example
Math.pow(3, 67) will have a value of 9.270946314789783e31 which means that any digit after the last 3 is lost. For this reason, after applying the modulo operation, you have no guarantee to get the right result (example).
This means that your code does not actually test what you think it does. This is inherent to the way floating point numbers work and you must change the way you hold your values to solve this problem. You could use long but then you would have problems with overflows (a long cannot hold a value greater than 2^64 - 1 so again, in the case of 3^67 you'd have another problem.
One solution is to use a class designed to hold arbitrary large numbers such as BigInteger which is part of the Java SE API.
As the others have noted, taking the power will quickly overflow. For example, if you are picking a number n to test for primality as small as say, 30, and the random number a is 20, 20^30 = about 10^39 which is something >> 2^90. (I took the ln of 10^39).
You want to use BigInteger, which even has the exact method you want:
public BigInteger modPow(BigInteger exponent, BigInteger m)
"Returns a BigInteger whose value is (this^exponent mod m)"
Also, I don't think that testing a single random number between 2 and n-1 will "prove" anything. You have to loop through all the integers between 2 and n-1.
#evthim Even if you have used the modPow function of the BigInteger class, you cannot get all the prime numbers in the range you selected correctly. To clarify the issue further, you will get all the prime numbers in the range, but some numbers you have are not prime. If you rearrange this code using the BigInteger class. When you try all 64-bit numbers, some non-prime numbers will also write. These numbers are as follows;
341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601, 7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705, 18705, 18721, 19951, 23001, 23377, 25761, 29341, ...
https://oeis.org/a001567
161038, 215326, 2568226, 3020626, 7866046, 9115426, 49699666, 143742226, 161292286, 196116194, 209665666, 213388066, 293974066, 336408382, 376366, 666, 566, 566, 666 2001038066, 2138882626, 2952654706, 3220041826, ...
https://oeis.org/a006935
As a solution, make sure that the number you tested is not in this list by getting a list of these numbers from the link below.
http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
The solution for C # is as follows.
public static bool IsPrime(ulong number)
{
return number == 2
? true
: (BigInterger.ModPow(2, number, number) == 2
? (number & 1 != 0 && BinarySearchInA001567(number) == false)
: false)
}
public static bool BinarySearchInA001567(ulong number)
{
// Is number in list?
// todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
// Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}