Rabin-Miller in Java - java

I got a function RSA program using BigInteger class.
However I generated my primes using the built in function. Instead, im asked to generate two primes, p and q via a Rabin-Miller test
The rabin-miller will run separately, I will generate two primes then enter them as static numbers in my RSA program, so they will be 2 separate programs.
The pseudo code for rabin-miller on wikipedia:
import java.math.BigInteger;
import java.util.Random;
public class MillerRabin {
private static final BigInteger ZERO = BigInteger.ZERO;
private static final BigInteger ONE = BigInteger.ONE;
private static final BigInteger TWO = new BigInteger("2");
private static final BigInteger THREE = new BigInteger("3");
public static boolean isProbablePrime(BigInteger n, int k) {
if (n.compareTo(ONE) == 0)
return false;
if (n.compareTo(THREE) < 0)
return true;
int s = 0;
BigInteger d = n.subtract(ONE);
while (d.mod(TWO).equals(ZERO)) {
s++;
d = d.divide(TWO);
}
for (int i = 0; i < k; i++) {
BigInteger a = uniformRandom(TWO, n.subtract(ONE));
BigInteger x = a.modPow(d, n);
if (x.equals(ONE) || x.equals(n.subtract(ONE)))
continue;
int r = 0;
for (; r < s; r++) {
x = x.modPow(TWO, n);
if (x.equals(ONE))
return false;
if (x.equals(n.subtract(ONE)))
break;
}
if (r == s) // None of the steps made x equal n-1.
return false;
}
return true;
}
private static BigInteger uniformRandom(BigInteger bottom, BigInteger top) {
Random rnd = new Random();
BigInteger res;
do {
res = new BigInteger(top.bitLength(), rnd);
} while (res.compareTo(bottom) < 0 || res.compareTo(top) > 0);
return res;
}
public static void main(String[] args) {
// run with -ea to enable assertions
String[] primes = {"1", "3", "3613", "7297",
"226673591177742970257407", "2932031007403"};
String[] nonPrimes = {"3341", "2932021007403",
"226673591177742970257405"};
int k = 40;
for (String p : primes)
assert isProbablePrime(new BigInteger(p), k);
for (String n : nonPrimes)
assert !isProbablePrime(new BigInteger(n), k);
}
}
Now my questions:
Out of this I will have to generate x number of primes, out of x number bitlength.
So lets say: generate 2 prime numbers out of 512 bits. Any idea how this could be done?
Also im supposed to generate 20 random a.
I guess I dont need the ending of the program or the code with top bottom
Just the mathetatical operations that represents rabin-miller and then somehow produce primes out of X bitlength
How would I do this?

OK, so you want to have a big integer in the range 2 ^ 511 to 2 ^ 512 - 1. That way you can be sure that the initial bit is set to one, making it a 512 bit random number. It may be kind of strange, but a 512 bit random number only contains 511 random bits; obviously the first bit cannot be zero because in that case the number is not 512 bits in size.
So to do this you need to generate a number between 0 and 2 ^ 511 - 1, then add 2 ^ 511 to it. Of course you want to use SecureRandom for secure key generation:
public static void main(String[] args) throws Exception {
int bitsize = 512;
SecureRandom rng = new SecureRandom();
for (int i = 0; i < 1000; i++) {
BigInteger randomForBitSize = createRandomForBitSize(bitsize, rng);
System.out.printf("%d : %X%n", randomForBitSize.bitLength(), randomForBitSize);
}
}
private static BigInteger createRandomForBitSize(int bitsize, Random rng) {
BigInteger randomFromZero = new BigInteger(bitsize - 1, rng);
BigInteger lowestNumberBitSize = BigInteger.valueOf(2).pow(bitsize - 1);
BigInteger randomBitSize = lowestNumberBitSize.add(randomFromZero);
return randomBitSize;
}

Related

Why doesn't my Fibonacci number with BigInteger that is 50000th number does not match with this website?

My Fibonacci Number Sequence Generator is something like below:
import java.math.BigInteger;
public class FibonacciGerenrate {
public static void FibonacciGenSerial(int n) {
BigInteger bgIntX = BigInteger.valueOf(0L);
BigInteger bgIntY = BigInteger.valueOf(1L);
BigInteger bgSwap = BigInteger.valueOf(0L);
BigInteger bgSwap2 = BigInteger.valueOf(0L);
for (long i = 0; i < n; ++i) {
if (i == 0) {
System.out.println(bgIntX);
}
if (i == 1) {
System.out.println(bgIntY);
}
if (i > 1) {
bgSwap = bgIntY;
//bgSwap2 = bgIntX;
bgSwap2 = bgSwap.add(bgIntX);
System.out.println(bgSwap2);
bgIntX = bgIntY;
bgIntY = bgSwap2;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
FibonacciGenSerial(50000);
}
}
But after two minutes the result of my 50000th Fibonacci number is given below. And it doesn't match with the output result of the following website. Why is that? Am I wrong? How can I fix it?
666100648565481205010951547560750933431950479937080994773751415475329647357449820574055869101354533179842571730518504252690058309030165957793611893184804604322634950697308315493285225827521968081167628872452768615738108939224876141123321314473270269465000697651877688322772577296187089266717271846243032342710169463007536900896948726682347470396722227545422828097990563697789828879621460065715309733855859315802250715487615816509617290450469997736430690473288367991638342872414940097748223932840620504428668520921655344430301224215692897710294618083941298394708009681899419228230959458929147242702905587860930816067641195022945573432258310501457406158453985387540996675518570815051459141923719868534748290307729399974816799507877982414057300447384236578708136869220018082040204979278639844104757994501020243076351266748128805893493483388168490769849952216805657010874821090514296406355110553853620293655313964806869929662365912232407486790482290214419052737478156102371122601126269716933969142851424928376050243479723763826825290719288650668925541910835478719090753282030915936853660001042090112056551037656921633144893206490532744723980391060344012105109041485463735778178695972346419842041360816069653760816717602148456722833643023802496324551697060976893855597905167037325153206289367148296194735202448911826351569038642836373273388438749220506838097571642903225609197374346730325128298541730100868662836408370652884683285634505652640553978383638747687616980404728716061328452648302998982054812903248737902508504748147966013614486993459268653853968661755091110112836831904518162502479003093926076241103832746864779503324612870238425655535310753031768424140386727074621268211011923361554582637672555763296766763854351892413797277286060361458119987282967951684241873325465716615261286317039991891544731713205149083895650120764948564143504675774742730781931928449575390256866738150275504189195079536502592392448642504625645222976625257159399314999623324197626795103321718324580761387037914189285639982327419211417271975071509612777714938378809871158377357033535038841919249248086467043409693138137112595014692834270711500010138506524349690071946393449648099208714463687090366864945411336246942663509789781079889019967268789357869074643331574973686481450223653389822460520183558105963223746605217997222387889751383509988082580944620464366163610679825916386927892295095374801191974096436340267734433730251299313389962413993201863403083841538686348160621073767578057926062012975065413640006600693103780549028905864574886005678966392854693541230730899811945995142389153270240354100999411437018828868859400252967613211726276446551737789380742131931227839657181988118865833480816151389108105528537216403964625087028986820520228715010685007591856614514778740893057418957567038483687071966812519841489146071253869889423050709567596610799719867036770761423744800930144446719985845639071948611549514167774740990909139060327587087707067165105903518512015008461478015071165612693027121166154673444805231514777642042786026879557204719340331591136844403791499153922402086325805819134623464621695959806096503918813601014444481497906000448189658304143531211623553079844917054983082998776950836009095453318030659296363742980120743822658798934449668379206415174607506093762182254110615681569717083211494114018772250097676725941157779174932734820568414226363304237968436842248075823282963543871105638202916945277814768864354916760621028779029538705578282925816579093772231288716013708194434438394149151491195572603314854012840149606398382269625517147771137052311883362797842053344005270594854159706295373797302632356629421276081517886019790032658026956610798949752129107805929458801027179475571809611111740758763373153476180800487503600606253740331201651721614058623392972202709529281690876761917422759364320015857427391270406331078878439305356665324344974924966088691546853401573510776119213632887236814855337852815095530230952927329556374671331803148352243251263283265128614261836045147294319819688471388326969417579904757464922708053628945150223335578551759081194695982876790011669825263518704133543095719051298714606579941128392101513434827920391242277081025094359551288317988893709534781978393945117097207076724791494616138837298981254940507843176701027248285993023860493750030475545967637215092330757914527051682535238578874169416419343826813276679317873998472471749686675765314934017559446883914428510562722864433439498146495120119913901346238077941728002849108235739773630267418055647587363776504486028675431129509545059403089455946519091959257301580675673458296214369105815004711115705568732078472962138306788772718702122766701488203167194502460046797772368844117678537000296384367003298371856809743914987011520470356450353074991325681614617984049912889619058746341502133349510556965392824027344424606453707377080729843402550151444160443240205434479868981609992585944572035786195485899532860763384337256250361518098480850231197439501006641686919198156639962949704149039218332928999679805750001308229279436709963263406239794882894065682638778935094093844765547146298281525989658002832701160413802748514986615725425904543562884354377218482717540397490074759993076664214614879978262310338197341128247873923938475147973518208725384873960246416763890489102999975017553478512459882618858334522285043766936484250110365909823001346728831403112210757004910897939860331633776262670716334868107386964506795963587304507408784081379727762610979152292320358478558706063821848616759228308451800969357027404759064318842378084092315173807524269604159146455211809665956036125198199064555802995538741179855329046922085858818028719242720320756267564991603927439237662286873972153269427651011235776687764275443675406561338563010027840718479862348591917953933994821284372280834889531645178403889948454266146190305939429767502629047826504253391658577635431374402785042293344010121069723509203600429348621981859733004535580888240359962243091362619987113834608216353140281542703151377407446724934788657087070356643740959095887668655129378518257991750140164754529691806673352241155899083959191871012780666725664381728302763413740883234510412767276595568556388063610723825329062674666971943247295036113072723265285584887408747520460330374437559798490506055045514064213832024627976351774570181205497658698375716324872741302409695277078424193438335439292377835057730034036145478052900402863148060495085323281842554651451036178213074357384018808581022331092529011187533277675824202856654414408717211908307376739819453635469072101848013176903862214060551709095000905074280971252452952909536451044791498647604893557873228056987657309671604147796665461589224998202540292423728222584648338588736664143022108815460974616828866988926345892872995571292422421773913479426380919060101391760420261420730453554287085513644899186880442361412631217758879550052882439598889457830856779410842513718768766091275135456380178178300617147751177790796952021354316582389053446353859076939551592384382774428962913131759132408131282868099485912859413029256311254587488212460831011124533510559924989863658143059250059774988707261404862833412102527976188330569397378668933475880809400830766736994040555356783641599760677810636466319728397018292100355127463837362740187333750034023892811300477151403790798603023100128610555550613790049616753892668808336749283366803306386255139739200520795547147713447959609503199036667286329077255924746918923652728312207868221104322516466728395553078246174620007843839145562059618308045132403907998960823112902275962909973027107655355753904048396067828089331591269404084934464120850296853594525628909527716103596016612755534356543244626443354995929675356741004157822959814523198218428406546177374802501921215250213079420934002604758784198250768562575771064769772000368187985559402552864559144184644579246642229835234324930558261825479606065297775518810717430372785680588824256604595020620542104279192252958742341699434491865985473991665889763758076619448944029251378170452192928104719929641595346467381297599346164809015557379482897429306632382718572359080200580125769912394268937425208471739498198294039857540747406725444057946732876949278204480286629256472353068058903699307994090916485647143450897246288120405624044272974581328543171842457960024273937994430303017416394043067083128885809213554212555454076560792542180784246519970324808557913497445167628369709876846332995607902679917364426349371775777894415979568094641873322943199022719563252749184400889845604530664204285868733579775816968832666680229105313367395422727986751689021732800376241526129309622574934865789670249661111729875503959405546498195859589055079973719910765291871059200578848376091382450827936346881093595641008636086660186437476419800866837924558581042971863841046902667299007595753977851094063304503639295603862415053601506791945752875688662852884259197089038836135664288165187408459281783504155854777313151613458774746417419908057567542628145693509766340480961263449080763343524370041474279899270297150716040301621228556313386834331553726237194024539232248304826810025215970632165794694360001925915558517317086796919038131136526735629682618234254690009699824548131542889727269915091378373526676061198785310756633059057477359341351019021807301233526081109778738179038665569950748548783317916516531990441083102618945701517010622590869651328033237579383625761930852080497002516434690134150677105528818731097339202012653039585356617091832439042951712221740827068604212723039524324615603136864188680891174417641489121494660755507003886549855291095862457104577939327455945605614519889510432311246894620989335653836679059538065437524829322117732552766511970700736821870037554214173785971048690499128614852714423373079479669815004079790437478405606774318669283764771464300583751653017433237361104801425733258035970901068212527401383741872107655688495567909246297629646550462643273447770343300210223279668754011716842718361977583092506467739884269913691250449405207875729401675856977466707283966223128881659500958944593836216397235863285323613591565012073847795737172930233933594485324619433561564931911914888793630226393645387832882895644605397261496725355227817783507292619445421611950535223331719341500756971803362136404519452880893229885903007294748984670394618952806821098740393146788700124820764553041872496073332651308037095119882100202710186702753433978399149908454238724269918322749507909772992037226532802201150761626111638906545107602875995114792979876216193958825864398145879704552311475748837637501
But this Fibonacci generator website outputs a different result:
50000th Fibonacci number by this website
Here we go:
public class FibonacciGerenrate {
public static void FibonacciGenSerial(int n) {
BigInteger bgIntX = BigInteger.valueOf(1L);
BigInteger bgIntY = BigInteger.valueOf(1L);
BigInteger result = BigInteger.valueOf(0L);
for (long i = 0; i < n; i++) {
if (i == 1) {
System.out.println(bgIntX);
}
if (i == 2) {
System.out.println(bgIntY);
}
if (i > 2) {
result = bgIntY;
result = result.add(bgIntX);
System.out.println("result: " + result);
bgIntX = bgIntY;
bgIntY = result;
}
}
}
public static void main(String[] args) {
FibonacciGenSerial(50000);
}
as the others already stated Fibonacci's sequence start from 1 not 0 . So basically, with your code you are getting the 49'999th Fibonacci's number.
I also improved your code to be a bit faster. No need for 2 swap fields.
Your number matches the 49999th number of the Fibonacci generator website you linked.
So i guess you have to do a little change in your for loop and add 1 iteration:
Change for(long i = 0; i < n;++i) { to for(long i = 0; i <= n;++i) {
You can avoid the 1 and 2 conditionals by simply printing out fib from the start, and then doing the swap.
Or you can just print 0 and 1 and then start the loop at i = 2, ensuring that you update the running series appropriately.
BigInteger start = BigInteger.ZERO;
BigInteger next = BigInteger.ONE;
BigInteger fib = start;
for (int i = 0; i < 10; i++) {
System.out.println(fib);
fib = start.add(next);
next = start;
start = fib;
}
Prints
0
1
1
2
3
5
8
13
21
34

Large Optimized IO processing in Java

An input n of the order 10^18 and output should be the sum of all the numbers whose set bits is only 2. For e.g. n = 5 setbit is 101--> 2 set bits. For n = 1234567865432784,How can I optimize the below code?
class TestClass
{
public static void main(String args[])
{
long N,s=0L;
Scanner sc = new Scanner(System.in);
N=sc.nextLong();
for(long j = 1; j<=N; j++)
{
long b = j;
int count = 0;
while(b!=0)
{
b = b & (b-1);
count++;
}
if(count == 2)
{
s+=j;
count = 0;
}
else
{
count = 0;
continue;
}
}
System.out.println(s%1000000007);
s=0L;
}
}
Java has a function
if (Integer.bitCount(i) == 2) { ...
However consider a bit: that are a lot of numbers to inspect.
What about generating all numbers that have just two bits set?
Setting the ith and jth bit of n:
int n = (1 << i) | (1 << j); // i != j
Now consider 31² steps, not yet 1000 with N steps.
As this is homework my advise:
Try to turn the problem around, do the least work, take a step back, find the intelligent approach, search the math core. And enjoy.
Next time, do not spoil yourself of success moments.
As you probably had enough time to think about Joop Eggen's suggestion,
here is how i would do it (which is what Joop described i think):
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
long sum = 0;
for (int firstBitIndex = 0; firstBitIndex < 64; firstBitIndex++) {
long firstBit = 1L << firstBitIndex;
if (firstBit >= n)
break;
for (int secondBitIndex = firstBitIndex + 1; secondBitIndex < 64; secondBitIndex++) {
long value = firstBit | (1L << secondBitIndex);
if (value > n)
break;
sum += value;
}
}
System.out.println(sum % 1000000007);
sc.close();
}
}
Java provides the class BigInteger, which includes a method nextProbablePrime(). This means you could do something like this:
BigInteger n = new BigInteger(stringInputN);
BigInteger test = BigInteger.valueOf(2);
BigInteger total = BigInteger.valueOf(0);
while (test.compareTo(n) < 0){
total = total.add(test);
test = test.nextProbablePrime();
}
System.out.println(total);
This this has an extremely low probability of getting the wrong answer (but nonzero), so you might want to run it twice just to doublecheck. It should be faster than manually iterating it by hand though.

How can I prevent the overlapping random numbers

How would i prevent duplicating numbers from random numbers.
I need to generate 5 numbers between 1 and 9 that are each different.
I would often get same numbers like 23334, how can i prevent that?
Any help would be great!
int num2 = (int) Math.round((Math.random()*9) +1);
int num1 = (int) Math.round((Math.random()*9) +1);
int num5 = (int) Math.round((Math.random()*9) +1);
int num3 = (int) Math.round((Math.random()*9) +1);
int num4 = (int) Math.round((Math.random()*9) +1);
One option is to use shuffle algorithm (e.g. Fisher-Yates shuffle ) to generate random sequence from 1 to 9, then take first 5 numbers of the sequence
Further explanation on StackOverflow: https://stackoverflow.com/a/196065/950427
Set<Integer> set=new HashSet<>();
while (set.size()<5) {
set.add( Math.round((Math.random()*9) +1));
}
After the set is filled you have 5 unique random numbers.
UPDATE: just to illustrate Jared Burrows' comment
Create a List includes the numbers that you want (1 to 9).
Generate random number from 0 to (size of the list minus 1).
Remove one element by index from the above generated random number. And add the removed element to a array which to be returned as a results
public static void main(String[] args) {
int []answers= returnRandomNonRepeatingNumbers(5,0,9);
for(int answer: answers) {
System.out.println(answer);
}
}
public static int[] returnRandomNonRepeatingNumbers(int sizeYouWant, int poolStart, int poolEnd) {
List<Integer> pool=new ArrayList<Integer>();
for(int i=poolStart;i<=poolEnd;i++) {
pool.add(i);
}
int []answers=new int[sizeYouWant];
for(int i=0;i<sizeYouWant;i++) {
//random index to be pick and remove from pool
int randomIndex = (int) Math.round((Math.random()*(pool.size()-1)));
answers[i]=pool.remove(randomIndex);
}
return answers;
}
If the number of possible random values is small, you want to use shuffle.
List<Integer> values = IntStream.range(0, 10).boxed().collect(toList());
Collections.shuffle(values);
values = values.subList(0, 5);
If the number of possible random values is large, you want to test adding them to a Set (or the original list if small enough)
Set<Integer> valueSet = new HashSet<>();
Random rand = new Random();
while(valuesSet.size() < 5) valuesSet.add(rand.nextInt(9) + 1);
List<Integer> values = new ArrayList<>(valueSet);
Collections.shuffle(values, rand);
Note: you need to shuffle the set as it doesn't preserve order. e.g. the numbers 1,2,3 will always come out in that order with HashSet, not 3,2,1.
Floyd's subset selection algorithm is designed to do exactly what you want, and is extremely efficient even for large sets. Selecting m items from a set of n is O(m) average running time, independent of n. Here's a Java implementation.
/*
* Floyd's algorithm to chose a random subset of m integers
* from a set of n, zero-based.
*/
public static HashSet<Integer> generateMfromN(int m, int n) {
HashSet<Integer> s = new HashSet<Integer>();
for (int j = n-m; j < n; ++j) {
if(! s.add((int)((j+1) * Math.random()))) {
s.add(j);
}
}
return s;
}
One possible approach to this problem can be divide & conquer. Step of following describes the approach:
Say m is the minimum & n is the maximum, within what i wanna get x number of randoms
Choose a random p between m & n. Save it to an array of answer. decrease x by 1 as we get one answer to our problem.
Now take a q a random number between m & p-1, another r a random number between p+1 & n. Fill up the answer array with q & r decrease x 1 for q and another 1 for the r.
Now carry on this process recursively, until the lower bound (m) & higher bound (n) becomes equal or x becomes 0.
Benefit: benefit of this approach is that, in worst case, it's runtime will be O(x), where x is the number of random number required. The best case scenarion is also o(x), as i have to find at least n number of random. These two comprise average case to θ(x) complexity.
import java.util.Random;
class GenerateDistinctRandom{
static int alreadyPut = 0;
static Random rand = new Random();
public static int[] generateDistinctRandom(int howMany, int rangeMin, int rangeMax)
{
int randomNumbers[] = new int[howMany];
GenerateDistinctRandom.recursiveRandomGenerator(rangeMin, rangeMax, randomNumbers, howMany);
return randomNumbers;
}
private static void recursiveRandomGenerator(int rangeMin, int rangeMax, int[] storage ,int storageSize)
{
if(rangeMax - rangeMin <= 0 || GenerateDistinctRandom.alreadyPut == storageSize)
{
return ;
}
int randomNumber = GenerateDistinctRandom.rand.nextInt(rangeMax-rangeMin) + rangeMin;
storage[GenerateDistinctRandom.alreadyPut] = randomNumber;
GenerateDistinctRandom.alreadyPut++;
//calling the left side of the recursion
recursiveRandomGenerator(rangeMin, randomNumber - 1, storage, storageSize);
recursiveRandomGenerator(randomNumber + 1, rangeMax, storage, storageSize);
}
public static void main(String []args){
int howMany = 5;
int distinctNumber[] = GenerateDistinctRandom.generateDistinctRandom(howMany 0, 9);
for(int i = 0;i < howMany;i++)
{
System.out.println(distinctNumber[i]);
}
}
}
I suppose you would need to store the ones that have been generated into an array and compare the new random number to the list to ensure it is unique.
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int[] numbers = new int[5];
int tempNumber = 0;
for(int numberCounter = 0; numberCounter < numbers.length;)
{
tempNumber = (int) Math.round((Math.random()*9) +1);
if(!contains(numbers, tempNumber)){
numbers[numberCounter++] = tempNumber;
}
}
}
public static boolean contains(final int[] numbersArray, final int tempNumber) {
for (final int numberFromArray : numbersArray) {
if (numberFromArray == tempNumber) {
return true;
}
}
return false;
}
I notice you did not use an array in your example, so in case you do not know how to use them yet, you could also make 5 variables.
int randomNumber = 0;
int firstNumber = Math.round((Math.random()*9) +1);
int secondNumber = 0;
while(secondNumber == 0){
randomNumber = Math.round((Math.random()*9) +1)l
if(randomNumber != firstNumber){
secondNumber = randomNumber;
}
}
And you could continue making while statements like that. But if you are supposed to know about arrays, you should definitely be using one to store the numbers.
How about this?
package com.se;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TestRandom {
List<Integer> comp = new ArrayList<>();
int listSize = 20;
public void doTask() {
Random ran = new Random();
int i = 0;
while(i < listSize){
int randomNumber = ran.nextInt(80) + 1;
if(!comp.contains(randomNumber)){
comp.add(randomNumber);
i++;
}
}
for(Integer num : comp){
System.out.println(num);
}
}
public static void main(String[] args) {
TestRandom testRandom = new TestRandom();
testRandom.doTask();
}
}

Using biginteger to find the sequence of sum of powers

Sum(N) =1^1+2^2+3^3+...+N^N
Using Java,
How would I use BigInteger to find the smallest integer N such that the value of Sum(N) is larger than 10^20?
I'm really stuck,please give me some advice
This is what I have so far:
import java.math.BigInteger;
public class PROJECTV1 {
public static void main(String [] args) {
BigInteger bResult= bigFunctionExample_2();
System.out.println(" => result_got:"+ bResult);
System.out.println(); //newline
}// end_main
public static BigInteger bigFunctionExample_2() {
BigInteger bSum = BigInteger.ZERO;
BigInteger bTmp;
String sSum;
// BigInteger bResult =0;
for (int i=1; ; i++) {
bTmp = BigInteger.valueOf(i);
bTmp = bTmp.pow(i); // i^i
bSum = bSum.add(bTmp); // sum = i^i+ (i-1)^(i-1)+ ....
sSum = bSum.toString();
if ( sSum.length() >21) {
System.out.println("i="+i +" bSum ="+bSum);
break;
}//
}//end_for
return bSum; // result
} // end_bigFunctionExample_2
}
Looking at your code, you have a line bTmp.pow(2). That squares the numbers in your series, but you need to raise bTmp to the bTmp power. Java doesn’t seem to want to take a BigInteger as an argument to pow, but you could replace pow with another for loop.
Also, sSum.length() >30 looks like it will only occur if your sum is greater than or equal to 1029. Is there a reason you convert the number to a string each time through the loop, rather than comparing the number to 1020? Perhaps you could put something like bSum > bMax as the test condition in your for loop, rather than leaving it blank and exiting with a break. Then you could make a new BigInteger bMax and set it to 1020 at the start of your code.
For testing, you could set bMax to something small, like 100, and see if your program gives the correct result. You can calculate the first few steps of the series by hand to check your program.
Here is a clue computing some factorials:
import java.math.*;
public class FactorialBig {
public static BigInteger factorial(BigInteger n) {
if (n.equals(BigInteger.ZERO))
return BigInteger.ONE;
else
return n.multiply(factorial(n.subtract(BigInteger.ONE)));
}
public static void main(String[] args) {
for (int n = 0; n < 20; n++) {
BigInteger f = factorial(new BigInteger(new Integer(n).toString()));
System.out.printf("factorial(%2d) = %20s%n", n, f.toString());
}
}
}
You know you should save the above as a file named "FacotrialBig.java".

Can't Generate Large Prime Numbers

I'm trying to generate large prime numbers in Java. I use BigIntegers for this. Here is my code to generate and store 10 prime numbers inside an array.
public static void primeGenerator() {
BigInteger[] primeList = new BigInteger[10];
BigInteger startLine = new BigInteger("10");
int startPower = 6;
BigInteger endLine = new BigInteger("10");
int endPower = 9;
int j = 0;
for (BigInteger i = fastExp(startLine,startPower);
i.compareTo(fastExp(endLine,endPower)) <= 0;
i = i.add(BigInteger.ONE)) {
if (checkPrimeFermat(i) == true && j < 10) {
primeList[j] = i;
j++;
}
}
System.out.println(primeList[0]);
System.out.println(primeList[1]);
System.out.println(primeList[2]);
System.out.println(primeList[3]);
System.out.println(primeList[4]);
System.out.println(primeList[5]);
System.out.println(primeList[6]);
System.out.println(primeList[7]);
System.out.println(primeList[8]);
System.out.println(primeList[9]);
}
I wrote my own fastExp function to generate numbers faster. Here are my other functions.
public static BigInteger getRandomFermatBase(BigInteger n)
{
Random rand = new Random();
while (true)
{
BigInteger a = new BigInteger (n.bitLength(), rand);
if (BigInteger.ONE.compareTo(a) <= 0 && a.compareTo(n) < 0)
{
return a;
}
}
}
public static boolean checkPrimeFermat(BigInteger n)
{
if (n.equals(BigInteger.ONE))
return false;
for (int i = 0; i < 10; i++)
{
BigInteger a = getRandomFermatBase(n);
a = a.modPow(n.subtract(BigInteger.ONE), n);
if (!a.equals(BigInteger.ONE))
return false;
}
return true;
}
public static void main(String[] args) throws IOException
{
primeGenerator();
}
public static BigInteger fastExp (BigInteger x, int n){
BigInteger result=x;
int pow2=powof2leN(n);
int residue= n-pow2;
for(int i=1; i<pow2 ; i=i*2){
result=result.multiply(result);
}
for(int i=0 ; i<residue; i++){
result=result.multiply(x);
}
return result;
}
private static int powof2leN(int n) {
for(int i=1; i<=n; i=i*2){
if(i*2>2)
return 1;
}
return 0;
}
}
So the problem is when I try it with small numbers (for example startPower=3, endPower=5) it generates and prints prime numbers. But when I try it with big numbers (for example startPower=5, endPower=7) it doesn't generate anything. How can I improve my code to work with large numbers?
Thank you
First of all, I would like to point out that you did not write this code. You stole it from here and claimed that you wrote it, which is incredibly unethical.
The code is correct. It's just slow. As you increase the power, the code takes increasingly longer. There are two reasons why this occurs:
The Fermat test takes increasingly longer to apply.
BigInteger operations take increasingly longer to execute.
The Fermat test grows like O(k × log2n × log log n × log log log n). BigInteger's addition and subtraction grow like O(n). Obviously, BigInteger is what is slowing you down.
Below is a profile of your code with the power set from 5 to 7.
If you want your code to produce larger and larger primes, you should focus on reducing the number of operations you do on BigIntegers. Here is one such improvement:
Take n.subtract(BigInteger.ONE) outside of your for loop. The result does not need to be calculated many times.
Further suggestions will have to come from the Mathematics folks over on Mathematics Stack Exchange.
Here is a much simpler solution for finding large primes -
BigInteger big = new BigInteger("9001");//or whatever big number you want to start with
BigInteger[] primes = new BigInteger[10];
for(int i=0;i<10;i++){
primes[i]=big=big.nextProbablePrime();
}
It has some limitations outlined here, but based on your code it should be more than enough.
you can use BigInteger(int bitLength, int certainty, Random rnd) constructor
BigInteger b= new BigInteger(20, 1, new Random());
It will generate a prime number for you. bitLength specifies the number of digits you want in your BigInteger, certainity specifies the amount of certainity you want that your BigInteger should be prime.

Categories