I am creating a small game for students, and in a place, it has to display the value of 27830457+1
I can call BigInteger's pow() method if the number is not this much big. Since the number is very big, that method is useless. How can I find the HUGE power of this kind of numbers? Please help!
Well in binary it's just 10000...01 with 7830456 zeros.
In decimal, there will be approximately two million digits, which is about 2 megabytes of storage. This is well within the feasibility of BigInteger with a default heap size.
In practice, it even uses exponentiation by squaring to compute it quickly (though not guaranteed by the specifications). However the conversion to a String will take some time since it's a linear time operation.
import java.math.BigInteger;
public class BigPow {
public static void main(String[] args) {
BigInteger result = (new BigInteger("2")).pow(27830457).add(BigInteger.ONE);
System.out.println(result);
}
}
Here's a version which will print out the digits slowly:
import java.math.BigInteger;
public class BigPow {
public static void main(String[] args) {
BigInteger result = (new BigInteger("2")).pow(27830457).add(BigInteger.ONE);
BigInteger powten = BigInteger.TEN.pow(2357202);
while(powten.compareTo(BigInteger.TEN) > 0) {
BigInteger digit = result.divide(powten).mod(BigInteger.TEN);
System.out.print(digit);
powten = powten.divide(BigInteger.TEN);
}
}
}
The first digits are:
27337386390628313557307248857732033008168556429738078791761607160549944954510637855005417718646965163546351365984857761796847950377880836291434244529029919271706271982523405687134334692691344477538489450971091437463160940371624647030064741968436401566711255284353690448270545402444641547030399228243743315193608710148721648879085592699913299745785392609301774185427367430782834290629265859073814466687714408436025809860462926275610087354595992436000187216152954542774991509992374985538879880897902639600451627914923043483436514419544413306391278529303650112773297502090619459167888563274071587848623085880067091968911236296732119252937497152769541579516150659424997041968213122450568364121976474269097910635641227922923398092242409755554115985855831015459204780391470591543281267373716556272259386683864538263922398723602210173800151405332100275913619559563575829498369806957031526077258236305186254269056811134135133350936924294101345294335698866339561918857584229744277901180792029180156485000086528174400878657004645726892816943589969701053158760210512171516969813345080894134663207988962182426459128577282934948790911691329475034324656384238413230485050607666988301932660490870167246016897007835866691705399794247746213819662270451531049826029606671683482160663572103374
Confirmed by WolframAlpha.
I don't know why you think BigInteger isn't up to this:
import java.math.BigInteger;
public class Test {
public static void main(String[] args) throws Exception {
BigInteger big = BigInteger.valueOf(2)
.pow(7830457)
.add(BigInteger.ONE);
System.out.println(big);
}
}
It takes a little while (particularly the string conversion at the end), but it's perfectly reasonable.
As Peter noted, shifting ONE left 7830457 is much neater, mind you. I'd argue it's a bit less clear - and of course it doesn't help in the string conversion part.
EDIT: Almost all of the time is spent in the string conversion. It finished in the end on my box though. I can't see the start of it any more, but it ends with...
08570502260645006898157834607641626568029302766491883299164453304032280181734737
79366998940913082443120328458954436211937775477966920836932628607888755839700303
873
You should be able to calculate this with BigInteger.
System.out.println(BigInteger.ONE.shiftLeft(7830457).add(BigInteger.ONE));
Try something like this:
BigInteger mant = new BigInteger("2");
BigInteger result = mant.pow(7830457).add(BigInteger.ONE);
Related
I'm getting StackOverflowError (Exception in thread "main" java.lang.StackOverflowError) for the following code. But the program works fine for m=3, n=3 (or other lower values) but does not work for m=4 and n=2 or 3.
public class AckermannFunction
{
static BigInteger One = BigInteger.ONE;
static BigInteger Zero = BigInteger.ZERO;
static BigInteger ackmnFun(BigInteger m, BigInteger n)
{
if (m.equals(Zero))
return n.add(One);
if (n.equals(Zero))
return ackmnFun(m.subtract(One), One);
return ackmnFun(m.subtract(One), ackmnFun(m, n.subtract(One)));
}
public static void main(String[] args)
{
BigInteger m = new BigInteger("4");
BigInteger n = new BigInteger("3");
System.out.println(ackmnFun(m, n));
}
}
There are too many recursive calls I understand. Is there any way to get rid of this error?
Thanks.
Rather than doing this recursively, you could approach it as a dynamic programming problem, and construct a table of values from the bottom up. Then rather than making recursive calls, you simply reference your table to create the next entry.
I've found a solution of my question by myself. I want to share it with you.
Since the Ackermann function calls itself for so many times even for a very low value of m & n, what I did, I added few more terminating condition up to m=3 and n=3 (to minimize recursive calls). And the tricks worked. I found initial values by running the original recursive function and then added all these as terminating condition.
The program finds the Ackermann(4,2) in a few seconds now. The answer is very long containing 19729 decimal digits.
I would expect this to return with 7, given the input of (2,2). Instead of getting a proper output, the program returns a java.lang.StackOverflowError at line 16.
package main;
import java.math.BigInteger;
public class Ackermann {
public static void main(String[] args) {
System.out.println(ack(BigInteger.valueOf(2),BigInteger.valueOf(2)));
}
public static BigInteger ack(BigInteger a, BigInteger b) {
BigInteger ans;
if (a.equals(0)) ans = b.add(BigInteger.ONE);
else if (b.equals(0)) ans = ack(a.subtract(BigInteger.ONE),BigInteger.valueOf(1));
else ans = ack(a.subtract(BigInteger.ONE), ack(a,b.subtract(BigInteger.ONE))); //line 16
return (ans);
}
}
I've increased the maximum stack size all the way up to 2GB, but it's still throwing the error at the small input of (2,2). Before I started using the BigIntegers instead of Longs, everything worked out fine with the input (2,2), but now it's a mess.
Instead of equals(0) you have to use equals(BigInteger.ZERO).
Otherwise you compare a BigInteger to an Integer (auto boxing) which will always be false.
I am pretty new to Java. I am learning numerical computation at the moment. How does one add and multiply a very small number and a very large number, say something of order $10^{-20}$ and something of order $10^{20}$ to arbitrary precision.
Take a look at the BigDecimal class. From the Javadoc:
Immutable, arbitrary-precision signed decimal numbers.
and:
The BigDecimal class gives its user complete control over rounding behavior.
For your example:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal big = new BigDecimal("10e20");
BigDecimal small = new BigDecimal("10e-20");
BigDecimal ans = big.add(small);
System.err.println("Answer: " + ans);
}
}
Running gives the following:
$ java Main
Answer: 1000000000000000000000.00000000000000000010
Try the following (didn't count the zeros). You may find other methods to construct 10^20/10^-20 more suitable.
System.out.println( new BigDecimal("0.0000000000000000000000000000001").add( new BigDecimal
("100000000000000000000000000000000")));
so I'm trying to make some code where it basically factors really big numbers. I've tried to translate the code that worked using longs into BigIntegers but the result just returns a lot of 2s and 0s. Here it is.
package primes;
import java.math.BigInteger;
public class Primes {
public static void main(String[] args) {
BigInteger y = new BigInteger("0");
BigInteger count= new BigInteger("2");
BigInteger input = new BigInteger("12321");
BigInteger one = new BigInteger("1");
while(input.compareTo(input)!=1) {
y=input.mod(count);
System.out.println(y);
if(y.compareTo(y)==0) {
input=input.divide(count);
System.out.println(count);
} else if(y.compareTo(y)!=0) {
count.add(one);
}
}
}
}
Alright, I see the problem with the count.add(one); but I am still unsure as to how the compareTo function works. Just for clarifciation with what each of these loops are supposed to do, I'm just going to paste the code of the functioning script that works with longs.
package longprimes;
public class LongPrimes {
public static void main(String[] args) {
long input = 121L;
long count = 2;
long y;
while (input!=1){
y = input%count;
if(y==0){
input = input/count;
System.out.println(count);
}
else if(y!=0){
count++;
}
}
}
}
Seemingly what is happening when I updated the BigInteger code a little bit is that it would factor it but it wouldn't divide input so that it would just keep finding the remainder but in the case that it was 0, it didn't actually divide input to end the loop.
Looks like this is a homework assignment, so I'll just point out a few things:
input.compareTo(input)!=1 is probably not what you intended. Ideally, you want to finish that while loop when input is one. But compareTo will return -1, 0 or 1 if the number on the left is less, equal to, or greater than the other number. Consider what this condition actually returns.
y.compareTo(y)==0 is kind of the same thing. You're comparing a number y with itself. Ideally, you want to compare with zero.
count.add(one) is not really doing anything. Consider what happens when you simply do
1 + 2;
you're computing the result of adding one to count but you're also ignoring the result. You might want to save that result somewhere.
I'm using this basic and crude code below for calculating prime numbers then exporting them to a text file:
import java.util.Scanner;
import java.io.*;
public class primeGenerator{
public static void main(String[] args)throws Exception {
Scanner kb = new Scanner(System.in);
String prime;
long num = kb.nextLong();
long i;
long z=0;
while(z==0){
for (i=2; i < num ;i++ ){
long n = num%i;
if (n==0){
break;
}
}
if(i == num){
writer(num);
}
num=num+2;
}
}
public static void writer(long num) throws Exception {
FileWriter writer = new FileWriter("prime.txt",true);
String prime= ""+ num;
writer.write(prime);
writer.write(" ");
writer.flush();
writer.close();
}
}
I would like to find primes beyond the Primative long's range and apparently big integer is the way to go about it. So how do i alter my code to do so?
Do you really need this? Having numbers bigger than can be handled by long means you want to test numbers bigger than 9223372036854775807. If your for-loop can test a hundred million divisions per second, it will still take it 2923 years to determine if that number is prime - and longer for larger numbers, of course.
A common optimization is to only test divisions up to sqrt(num). If you haven't found anything then, the number is prime.
Well, use BigInteger wherever you've currently got long. Instead of using % you'll use mod, instead of incrementing you'll use i = i.add(BigInteger.ONE), instead of == 0 you'll use equals(BigInteger.ZERO) etc.
Use Scanner.nextBigInteger instead of Scanner.nextLong, too.
Given that this looks like homework of some description (possibly self-set, of course) I won't write out the whole code for you - but if you have specific problems, feel free to ask.