I have a series of BigInteger problems that require the use of constantly increasing a BigInteger. I proposed a loop, but that is extremely tricky due to the fact that BigIntegers and BigDecimals are immutable.
Here is an example of one of the programs I am trying to make. It is a method trying to find BigIntegers larger than Long.MAX_VALUE that are divisible by 2 or 3.
public void divisibleBy2Or3() {
BigInteger min = new BigInteger("9223372036854775808");
int j = 0;
BigInteger increment = new BigInteger("1");
BigInteger divideBy2 = new BigInteger("2");
BigInteger divideBy3 = new BigInteger("3");
while (j < 10) {
BigInteger a = min.add(increment);
BigInteger b = a.divide(divideBy2); BigInteger c = a.divide(divideBy3);
if (b.multiply(divideBy2) == a || c.multiply(divideBy3) == a) {
System.out.print(a + " ");
j++;
}
}
}
The problem with this code is I can't seem to figure out how to get the BigInteger that I am testing for each iteration of the loop to add itself with each iteration. I'm also a little unsure as to if the multiply methods actually work for this scenario, as whenever I run the program, it hangs and shows a blank console
You need to keep track of your current value using a variable declared outside the loop - otherwise it keeps going back to min + 1.
static final BigInteger ONE = BigInteger.ONE;
static final BigInteger TWO = ONE.add(ONE);
static final BigInteger THREE = TWO.add(ONE);
public void divisibleBy2Or3() {
BigInteger min = new BigInteger("9223372036854775808");
int j = 0;
// Add this.
BigInteger value = min;
while (j < 10) {
value = value.add(ONE);
BigInteger b = value.divide(TWO);
BigInteger c = value.divide(THREE);
if (b.multiply(TWO).equals(value) || c.multiply(THREE).equals(value)) {
System.out.print(value + " ");
j++;
}
}
}
Related
Fibonacci sequence is defined as a sequence of integers starting with 1 and 1, where each subsequent value is the sum of the preceding two I.e.
f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2) where n>=2
My goal is to calculate the sum of the first 100 even-values Fibonacci numbers.
So far I've found this code which works perfectly to calculate the sum of even numbers to 4million , however I'm unable to find edit the code so that it stops at the sum of the 100th value, rather than reaching 4million.
public class Improvement {
public static int Fibonacci(int j) {
/**
*
* Recursive took a long time so continued with iterative
*
* Complexity is n squared.. try to improve to just n
*
*/
int tmp;
int a = 2;
int b = 1;
int total = 0;
do {
if(isEven(a)) total +=a;
tmp = a + b;
b = a;
a = tmp;
} while (a < j);
return total;
}
private static boolean isEven(int a) {
return (a & 1) == 0;
}
public static void main(String[] args) {
// Notice there is no more loop here
System.out.println(Fibonacci(4_000_000));
}
}
Just to show the console from #mr1554 code answer, the first 100 even values are shown and then the sum of all is 4850741640 as can be seen below:
Any help is appreciated, thanks!
You need to use BigInteger because long easily overflows as Fibonacci's scales quite easily. BigInteger is also tricky to check whether is an odd or even number, but you can use BigInteger::testBit returning boolean as explained in this answer.
Here is some complete code:
BigInteger fibonacciSum(int count, boolean isOdd) {
int i = 0;
BigInteger sum = BigInteger.ZERO;
BigInteger current = BigInteger.ONE;
BigInteger next = BigInteger.ONE;
BigInteger temp;
while (i < count) {
temp = current;
current = current.add(next);
next = temp;
if ((current.testBit(0) && isOdd) || ((!current.testBit(0) && !isOdd))) {
sum = sum.add(current);
i++;
}
}
return sum;
}
Or you can have some fun with Stream API:
BigInteger fibonacciSum(int count, boolean isOdd) {
final BigInteger[] firstSecond = new BigInteger[] {BigInteger.ONE, BigInteger.ONE};
return Stream.iterate(
firstSecond,
num -> new BigInteger[] { num[1], num[0].add(num[1]) })
.filter(pair ->
(pair[1].testBit(0) && isOdd) ||
(!pair[1].testBit(0) && !isOdd))
.limit(count)
.map(pair -> pair[1])
.reduce(BigInteger.ZERO, BigInteger::add);
}
In any way, don't forget to test it out:
#Test
void test() {
assertThat(
fibonacciSum(100, false),
is(new BigInteger("290905784918002003245752779317049533129517076702883498623284700")));
}
You said.
My goal is to calculate the sum of the first 100 even-values Fibonacci numbers.
That number gets very large very quickly. You need to:
use BigInteger
use the mod function to determine if even
For this I could have started from (1,1) but it's only one term so ...
BigInteger m = BigInteger.ZERO;
BigInteger n = BigInteger.ONE;
BigInteger sumOfEven= BigInteger.ZERO;
int count = 0;
BigInteger t;
while( count < 100) {
t = n.add(m);
// check if even
if (t.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {
sumOfEven = sumOfEven.add(t);
count++;
}
n = m;
m = t;
}
System.out.println(sumOfEven);
Prints
290905784918002003245752779317049533129517076702883498623284700
If, on the other hand, from your comment.
My aim is to calculate the sum of the first 100 even numbers
Then you can do that like so
sumFirstNeven = (((2N + 2)N)/2 = (N+1)N
so (101)100 = 10100 and the complexity is O(1)
as I figured, you want a program to sum 100 first even values of the Fibonacci series.
here is a sample code, when you run the program it will ask you to determine the number of the even values, you want 100 value e.g, type 100 in consul:
public static void main(String[] args) {
int firstNumber = 0;
int secondNumber = 2;
System.out.print("Enter the number of odd elements of the Fibonacci Series to sum : ");
Scanner scan = new Scanner(System.in);
int elementCount = scan.nextInt(); // number of even values you want
System.out.print(firstNumber + ", ");
System.out.print(secondNumber + ", ");
long sum = 2;
for (int i = 2; i < elementCount; i++) {
int nextNumber = firstNumber + secondNumber;
System.out.print(nextNumber + ", ");
sum += (nextNumber);
firstNumber = secondNumber;
secondNumber = nextNumber;
}
System.out.print("...");
System.out.println("\n" + "the sum of " + elementCount + " values of fibonacci series is: " + sum);
}
I`m trying to solve the "prime generator" in SPOJ, finding prime using the 2^(n-1)%n==1, but it becomes greater for integer, long at some point, therefore I tried BigInteger, and even now it is not showing output.
I have already tried various other techniques, but they quite plainly exceed the time limit, wanted to try something else except SOE algorithm.
import java.io. * ;
import java.math. * ;
import java.util. * ;
import java.util.Scanner;
class Scratch {
public static void main(String[] args) {
Scanner in =new Scanner(System. in );
int t = in.nextInt();
for (int i = 0; i < t; i++) {
BigInteger a = in.nextBigInteger();
BigInteger b = in.nextBigInteger();
for (BigInteger j = a; j.compareTo(b) < -1; j.add(BigInteger.ONE)) {
BigInteger n = j;
BigInteger r = new BigInteger("2");
int wow = n.intValue();
BigInteger y = r.pow(wow - 1);
System.out.println(y);
if ((y.mod(n)).compareTo(BigInteger.ONE) == 0)
System.out.println(j);
}
}
}
Does not show any output now.
In your for loop, you don't increment j.
for (BigInteger j = a; j.compareTo(b)<-1;
j.add(BigInteger.ONE)) {
j.add(...) won't change j, instead it returns a new BigInteger.
To fix your code, just assign the result of j.add(BigInteger.ONE) to j:
for (BigInteger j = a; j.compareTo(b)<-1;
j = j.add(BigInteger.ONE)) {
Bottom line: Please try to debug your code before posting it on StackOverflow.
Use an IDE of your choice.
This kind of errors happen, but they are easily cached if you debug your code and just mindlessly step through the program until you wonder why it did not advance yet.
Want to replace BigInteger loop in Java Stream API.
Below code, I have to modify in java8 using Stream API. Because of performance concerns.
My question what would be the best practice to change below code into best performance.
public BigInteger getSum(BigInteger n, BigInteger c) {
BigInteger sum = BigInteger.ZERO;
for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i=i.add(BigInteger.ONE)) {
sum = sum.add(calculateProduct(i, i.subtract(BigInteger.ONE), c));
}
return sum;
}
private BigInteger calculateProduct(BigInteger i, BigInteger j, BigInteger c) {
if (j.compareTo(BigInteger.ZERO) < 0) return BigInteger.ZERO;
if (j.compareTo(BigInteger.ZERO) == 0) return BigInteger.ONE;
if ((i.subtract(j).compareTo(c)) <= 0){
return j.add(BigInteger.ONE).multiply(calculateProduct(i, j.subtract(BigInteger.ONE), c));
}else
return BigInteger.ONE;
}
It looks like you are adding up products of sliding window of width c. If you want to improve performance, get rid of recursion and avoid recomputing the entire product. Use the product computed in the previous step: multiply it by the number entering the window and divide by the number exiting the window. Division is slower but it will pay off for larger values of c.
Finally, while I will keep your method signature, you really only need BigInteger as return.
BigInteger getSum(BigInteger n, BigInteger c) {
BigInteger p = BigInteger.ONE, sum = BigInteger.ZERO;
for (BigInteger x = BigInteger.ONE; x.compareTo(n) < 0; x = x.add(BigInteger.ONE)) {
p = p.multiply(x);
if (x.compareTo(c) > 0) {
p = p.divide(x.subtract(c));
}
sum = sum.add(p);
}
return sum;
}
If you want to speed it up further, you can use a bit of math to avoid having to divide at every step. Your sum can be broken up into s1 = sum[1,c) x! and s2 = sum[c,n) x!/(x-c)!. The second sum equals n!/(n-c-1)!/(c+1) (follows from hockey stick identity). The method below does not handle the trivial case of c >=n. I will leave that to you.
private static BigInteger fasterSum(BigInteger n, BigInteger c) {
assert c.compareTo(n) < 0;
BigInteger sum = ZERO, p = ONE;
for (BigInteger x = ONE; x.compareTo(c) < 0; x = x.add(ONE)) {
p = p.multiply(x);
sum = sum.add(p);
}
// sum[c,n) x!/(x-c)! = n!/(n-c-1)!/(c+1)
p = ONE;
for (BigInteger x = n.subtract(c); x.compareTo(n) <= 0; x = x.add(ONE)) {
p = p.multiply(x);
}
sum = sum.add(p.divide(c.add(ONE)));
return sum;
}
So I assume you want to add a list of BigInteger:
You can do that by using a reduce operation (https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html)
List<BigInteger> list = new ArrayList<>();
list.add(BigInteger.valueOf(5));
list.add(BigInteger.valueOf(1));
list.add(BigInteger.valueOf(3));
list.add(BigInteger.valueOf(10));
list.add(BigInteger.valueOf(2));
BigInteger sum = list.stream().reduce((x, y) -> x.add(y)).get();
System.out.println(sum);
That will calculate the sum, an equivalent would be:
BigInteger sum = list.stream().reduce(BigInteger::add).get();
You could also write an own Collector that is reusable and extract the reduce operation to there:
public static Collector<BigInteger, ?, BigInteger> calculateSum() {
return Collectors.reducing(BigInteger.ZERO, BigInteger::add);
}
and then do:
BigInteger sum = list.stream().collect(calculateSum());
I've written this little program to find n!:
public class Fattoriale {
public static void main (String[] args){
int n;
do {
n = Input.readInt("Enter an int number ( int >=0)");
while( n < 0);
long fatt = 1;
for (int i = 2; i <= n; i++){
fatta = fatt * i;
}
System.out.println(n"+!" + " = " + fatt);
Now I'm trying to rewrite this program using BigInteger. I've written this:
import jbook.util.*;
import java.math.*;
public class Fattoriale {
public static void main (String[] args){
String s = Input.readString("Enter an int number. ");
BigInteger big = new BigInteger(s);
BigInteger tot = new BigInteger("1");
BigInteger i = new BigInteger("2");
for (; i.compareTo(big) < 0; i.add(BigInteger.ONE)){
tot = tot.multiply(i);
}
System.out.println(tot);
}
}
But this program with BigInteger makes a loop and I can't understand why. I hope somebody can help me. Thank you very much ;). (nb. ignore Input class, it's only a class that I created to enter input faster)
This should be like this because i.add(BigInteger.ONE) doesn't update the variable i.
for (; i.compareTo(big) <= 0; i=i.add(BigInteger.ONE)) {
tot = tot.multiply(i);
}
There are two changes:
It should be <=0 instead of <0
Assign it back to i to update it.
How to confirm?
BigInteger i = new BigInteger("2");
System.out.println(i.add(BigInteger.ONE)); // print 3
System.out.println(i); // print 2
BigInteger is immutable, so unless you set a new value for it using the = operator, its value doesn't change. Thus, each time in the loop that you call i.add(BigInteger.ONE), the computer calculates i+1 and then throws away the result. Instead, try:
for (; i.compareTo(big) < 0; i=i.add(BigInteger.ONE)){
Another BigInteger problem. My code works for int and long, but since the test cases in UVa are larger, I need to use BigInteger. But I don't know how to use BigInteger and it drives me nuts! The code doesn't even enter the for-loop. It seems to be stuck in the condition part.
I tried using for or while, and they have the same problem.
public class Main{
public static void main(String[] asdf){
Scanner pp = new Scanner(System.in);
int testCases = pp.nextInt();
while(testCases-- > 0){
//BigInteger a = pp.nextBigInteger();
BigInteger low = pp.nextBigInteger();
BigInteger upp = pp.nextBigInteger();
BigInteger max = BigInteger.ZERO;
BigInteger i = low;
//((i.compareTo(upp)==-1)||
//(i.compareTo(upp)==0));
//i.add(BigInteger.ONE))
while((i.compareTo(upp))<0){
if(divCount(i).compareTo(divCount(max))==1){
max = i;
}
i.add(BigInteger.ONE);
}
System.out.println("Between "+low+" and "+upp+", "+max+" has a maximum of "+divCount(max)+" divisors.");
}
}
public static BigInteger divCount(BigInteger n){
BigInteger lim = n;
BigInteger size = BigInteger.ZERO;
BigInteger i = BigInteger.ONE;
while(i.compareTo(lim)<0){
if((n.mod(i).compareTo(BigInteger.ZERO))==0){
lim = n.divide(i);
if(!(lim.equals(i))){
size.add(BigInteger.ONE);
}
size.add(BigInteger.ONE);
}
i.add(BigInteger.ONE);
}
//return size;
return BigInteger.ONE;
}
}
i.add(BigInteger.ONE) does not modify i. Instead it returns a new object. Assign the value to i to get the effect you want. Same holds true for the other similar calls in your code.