Java - Converting to BigInteger - java

I build a program to find out the largest prime factor of 2^1000. It worked, and gave the right answers to my smaller test numbers, but then I realized that for my number I would have to use BigInteger. I've never used it before so I'm pretty sure I did something wrong. The BigInteger program doesn't give me back anything and doesn't finish running.
Here's the program, using primitive data types, that works:
public class PE3 { public static void main(String[] args) {
int num = 13195;
//find factors of 'num'
for (int i=(num); i>2; i--) {
if ((num%i)==0)
testPrime(num, i);
}
}
// find if factor is prime
public static void testPrime(int num, int i){
for (int j=2; j<i; j++) {
if ((i%j)==0)
break;
if (j==(i-1))
System.out.println(i);
}
}}
Here's (what I think is) the same program using BigInteger:
import java.math.BigInteger;
public class PE3BI { public static void main(String[] args) {
BigInteger num = new BigInteger("600851475143");
BigInteger zero = new BigInteger("0");
BigInteger one = new BigInteger("1");
BigInteger two = new BigInteger("2");
//find factors of 'num'
for (BigInteger i = new BigInteger("600851475143"); i.compareTo(two)==1; i.subtract(one)) {
if ((num.mod(i))==zero)
testPrime(num, i, one, zero);
}
}
// find if factor is prime
public static void testPrime (BigInteger num, BigInteger i, BigInteger one, BigInteger zero){
for (BigInteger j = new BigInteger("2"); j.compareTo(i)==-1; j.subtract(one)) {
if ((i.mod(j))==zero)
break;
if (j.compareTo(i.subtract(one))==0)
{System.out.println(i);
System.exit(0); }
}}}

While, piotrek's answer will solve one of your problems, your program still won't work.
Need to do's:
Don't use == for comparisons. It doesn't work for non-primitives, such as BigInteger(piotrek)
i.subtract(one) as the last item in a loop does nothing. Use i = i.subtract(one) and the equivalent for j.
Would be good:
Although technically correct, a.compare(b) == -1 and a.compare(b) == +1 are typically not the best practice for code readability and it might not be the case that compare returns one of these three values in all situations, so don't get in the habit. Use a.compare(b) < 0 and a.compare(b) > 0 instead.

you can't do comparisons like object == zero. it works only for primitives. now, your numbers are objects so it checks if reference is the same. change it to compare or equals

It might be better to use a long instead of the BigInteger class?
I just made this using your code to check if a number is prime or not prime:
long num = 600851475143L;
boolean prime = true;//Check this after for loop for prime.
for (long i=2; i<num; i++) {//Loops through all numbers between 2 and the number given to test.
if ((num%i)==0){//This is true if number is not prime.
prime = false;
System.out.println("Not prime: " + i);
break;
}
}

Related

Java Compute C(n,k) and factorial with biginteger

I want to compute the answer of C(n,k),such as C(10,2)=10*9/2*1 = 45
If I test my code by small numbers like 10, the code works.
However, when I try to compute C(1000,900), it compiles
Exception in thread "main" java.lang.ArithmeticException: / by zero
I've seen someone says it should use BigInteger,But after I tried, it still has errors.
For example: I change int factorial into BigInteger factorial,
while the for loop in cSelect, I can not change int i into BigInteger type,
As result, the answer up/factorial(y) has errors.
Please help me to fix this problem. Thanks!!
public class Test {
// Write a factorial function
static int factorial(int m) {
int result =1;
for (int i=2; i<=m; i++) {
result = result*i;
}
return result;
}
// Caculate C(x,y)
static int cSelect(int x, int y) {
int up=1;
for(int i=x; i>=(x-y+1); i--) {
up = up*i;
}
return up/factorial(y);
}
public static void main(String[] args) {
System.out.println(cSelect(1000,900));
}
}
Your code is fairly easy to translate in factorial. Start with ONE, multiply by the BigInteger.valueOf(long) for each i in your loop. Like,
// Write a factorial function
static BigInteger factorial(int m) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= m; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
Your other function does exactly the same, plus a division by the result of factorial(y). Like,
// Caculate C(x,y)
static BigInteger cSelect(int x, int y) {
BigInteger up = BigInteger.ONE;
for (int i = x; i >= (x - y + 1); i--) {
up = up.multiply(BigInteger.valueOf(i));
}
return up.divide(factorial(y));
}
With no other changes I get
63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890
Which I assume is correct.
First, return value must be BigInteger, because result of C(1000,900) far exceeds the range on an int.
Second, you don't need separate factorial() method. Doing the division as you iterate will improve memory footprint by not creating excessively large intermediate values (at cost of doing multiple divisions, but even so it might actually be faster).
Like this:
static BigInteger cSelect(int x, int y) {
BigInteger v = BigInteger.ONE;
for (int i = x, j = 1; j <= y; i--, j++)
v = v.multiply(BigInteger.valueOf(i)).divide(BigInteger.valueOf(j));
return v;
}
By counting i down and j up, there will never be a fraction from the division.
Test
System.out.println(cSelect(10, 2));
System.out.println(cSelect(1000, 900));
Output
45
63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890
You have to use BigInteger to do the calculation.
The value you are trying to compute is approximately 6.385051192630516e+139 and it is not representable as a Java primitive integer value.
Even if the result was representable, the reason you are getting divide by zero errors is that the divisor expression 900! ∗ 100! is overflowing to zero. You then divide by that zero.
The reason that it overflows to zero is that it is divisible by 2^32 and 2^64. That can be proven by using some simple algebra to compute the number of factors of 2 there are in 900! and 100!

Java program that converts binary numbers to decimal numbers. The input is a string of zeros and ones

I have to create a java program that converts binary to decimal using the following steps. Being new at this I did something, but I don't know what I did wrong or how to continue.
public class BinaryToDecimal {
public static void main(String args[]){
long sum = 0;
int result;
String s = "1001010101011010111001011101010101010101";
for(int i = s.length()-1; i <= 0; i--){
result = (int)Math.pow(2, i);
if(s.charAt(i) == '1')
sum=sum + result;
}
System.out.println(sum);
}
}
Use a loop to read (charAt()) each digit (0/1 char) in the input string, scanning from right to left;
Use the loop to build the required powers of 2;
Use a conditional statement to deal with 0 and 1 separately;
Debug using simple input, e.g. 1, 10, 101, and print intermediate values in the loop.
Use your program to find the decimal value of the following binary number:
1001010101011010111001011101010101010101
Do this only if your decimal value is at most 2147483647 or the maximum value an int can be in Java. If you don't know, just check the length of your string. If it's less than or equal to 32 i.e. 4 bytes, then you can use parseInt.:
int decimalValue = Integer.parseInt(s, 2);
Refer HERE for more info on the Integer.parseInt();
But if it's more, you can use your code. I modified your loop which is where your problem was:
String s = "1001010101011010111001011101010101010101";
long result = 0;
for(int i = 0; i < s.length(); i++){
result = (long) (result + (s.charAt(i)-'0' )* Math.pow(2, s.length()-i-1));
}
System.out.println(result);
The first thing I notice is that your binary number has more than 32 bits. This cannot be represented in the space of an int, and will result in overflow.
As a simpler answer, I ran the following and got the correct value at the end, it just uses simple bit shifts.
For each index in the string, if the character is 1, it sets the corresponding bit in the result.
public class BinaryToDecimal {
public static void main(String[] args) {
long sum;
String bin = "1001010101011010111001011101010101010101";
sum = 0;
for (int i = 0; i < bin.length(); i++) {
char a = bin.charAt(i);
if (a == '1') {
sum |= 0x01;
}
sum <<= 1;
}
sum >>= 1;
System.out.println(sum);
}
}
The loop runs from i = s.length()-1 until i <= 0. This should be i>=0.
The next problem is "int result". It works fine with result as a long ;) (Reason: You calculate a 40-bit value at the MostSignificantBit, but Integers only use 32-bit)
Also: You start at the rightmost Bit with i=s.length()-1. But the power that you calculate for it is 2^(s.length()-1) though it should be 2^0=1.
The solution is: result = (long)Math.pow(2, s.length()-1-i)
Edit:
I really like the solution of user2316981 because of its clear structure (without Math.pow, should be faster by using shift instead). And loops from 0 to MSB as I do with Double&Add algorithm. Can't comment on it yet, but thanks for the reminder ;)
import java.util.*;
import java.lang.Math;
class deci {
int convert(int n) {
int tem=1,power=0;
int decimal=0;
for (int j=0;j<n;j++) {
if(n==0) {
break;
} else {
while(n>0) {
tem=n%10;
decimal+=(tem*(Math.pow(2,power)));
n=n/10;
power++;
}
}
}
return decimal;
}
public static void main(String args[]) {
System.out.print("enter the binary no");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
deci dc=new deci();
int i=dc.convert(n);
System.out.print(i);
}
}

How to calculate and display large numbers in java

How could I calculate and display all digits of large numbers like 9999! (factorial of 9999) in java?
Take a look at this url which calculates 9999! and dislays all digits.
Use BigInteger, his limit is your memory
public static BigInteger factorial(BigInteger num) {
if (num.compareTo(new BigInteger("1")) < 0) {
return new BigInteger("1");
} else {
return factorial(num.subtract(new BigInteger("1"))).multiply(num) ;
}
}
Use BigInteger; 9999! took 120 ms with Java 8. Here is a version that uses longs, and halves that time:
public static BigInteger factorial(int n) {
// Try first to use longs in calculating the factorial.
BigInteger result = BigInteger.ONE;
long factor = 1;
for (int i = n; i > 1; --i) {
if Long.MAX_VALUE / factor < i) { // Overflow?
result = result.multiply(BigInteger.valueOf(factor));
factor = i;
} else {
factor *= i;
}
}
return result.multiply(BigInteger.valueOf(factor));
}
The Java standard library provide a BigInteger class, which can represent unlimited integer values (actually, they are limited, but only by available memory).
Not the fastest, but not really slow either.
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
You can use Strings (yes don't get astonished, you can!). A program can be created in strings to multiply two very large numbers (here i am talking about numbers say 5000 digits in length, each!)
I have already created them for addition and subtraction and it's not that hard to create it for Multiplication and i assure you that, though you will think that using BigInteger will be faster, but using Strings would be Ultrafast as compared to BigInt.
And the thing that slipped my mid, i used StringBuilder class to make the program more efficient.

Is there a better (more correct) way to calculate modulus of some power than Math.pow?

Consider the following simple block of Java code:
public static void main(String[] args) {
int a = 7;
double exp;
for (int i=0; i<71; ++i) {
exp = Math.pow(a,i) % 71;
if (exp == 59.0)
System.out.printf("k=%d: %.0f%n", i, exp);
}
}
I am trying to iterate through all of the exponents k such that a^x=59 mod 71... however there should be only a single one, and I'm getting three: k=3, k=23, k=63. This is clearly wrong, as upon verification, only k=3 is the correct answer. Is there some inherent problem in the way floating point works (and thus Math.pow), or is there some other logic problem in my code? Should I be using some other method to calculate a^x (mod n)?
The simplest correct expedient that doesn't require writing your own method is probably
BigInteger.valueOf(a)
.modPow(BigInteger.valueOf(i), BigInteger.valueOf(71))
.intValue();
If you want to avoid "big calculations", then you can perform the modulo after every multiplication:
public static void main(String[] args)
{
for (int i=0,a=1; i<71; i++, a = (a*7)%71)
{
if (a == 59)
System.out.println("k = " + i);
}
}

Project Euler Number 3

First of all, this isn't homework... working on this outside of class to get some practice with java.
public class Problem3 {
public static void main(String[] args) {
int n = 13195;
// For every value 2 -> n
for (int i=2; i < n; i++) {
// If i is a multiple of n
if (n % i == 0) {
// For every value i -> n
for (int j=2; j < i; j++) {
if (n % j != 0) {
System.out.println(i);
break;
}
}
}
}
}
}
I keep modifying the code to try to make it do what I want.
As the problem says, you should be getting 5, 7, 13 and 29.
I get these values, plus 35, 65, 91, 145, 203, 377, 455, 1015, 1885, and 2639. I think I'm on the right track as I have all the right numbers... just have a few extras.
And in checking a few of the numbers in both being divisible by n and being prime numbers, the issue here is that the extra numbers aren't prime. Not sure what's going on though.
If anyone has any insight, please share.
This part
for (int j=2; j < i; j++) {
if (n % j != 0) {
System.out.println(i);
break;
}
doesn't check whether i is prime. Unless i is small, that will always print i at some point, because there are numbers smaller than i that don't divide n. So basically, that will print out all divisors of n (It wouldn't print the divisor 4 for n == 12, for example, but that's an exception).
Note also that the algorithm - using long instead of int to avoid overflow - even if fixed to check whether the divisor i is prime for deciding whether to print it, will take a long time to run for the actual target. You should investigate to find a better algorithm (hint: you might want to find the complete prime factorisation).
I solved this problem in Java and looking at my solution the obvious advice is start using BigInteger, look at the documentation for java.math.BigInteger
Also a lot of these problems are "Math" problems as much as they are "Computer Science" problems so research the math more, make sure you understand the math reasonably well, before coming up with your algorithm. Brute force can work some times, but often there are tricks to these problems.
Brut force can also work for checking whether factor is prime or not for this problem...
eg.
for(i=1;i<=n;i++)// n is a factor.
{
for(j=i;j>=1;j--)
{
if(i%j==0)
{
counter++;// set counter=0 befor.
}
if(counter==2) // for a prime factor the counter will always be exactly two.
{
System.out.println(i);
}
counter=0;
}
}
Don't know about Java but here is my C code if it is of any help.
# include <stdio.h>
# include <math.h>
// A function to print all prime factors of a given number n
void primeFactors(long long int n)
{
// Print the number of 2s that divide n
while (n%2 == 0)
{
printf("%d ", 2);
n = n/2;
}
int i;
// n must be odd at this point. So we can skip one element (Note i = i +2)
for ( i = 3; i <= sqrt(n); i = i+2)
{
// While i divides n, print i and divide n
while (n%i == 0)
{
printf("%d ", i);
n = n/i;
}
}
// This condition is to handle the case whien n is a prime number
// greater than 2
if (n > 2)
printf ("%ld ", n);
}
/* Driver program to test above function */
int main()
{
long long int n = 600851475143;
primeFactors(n);
return 0;
}
Its very good that you are working on such problems out of class.
Saw your code. You are writing a procedural code inside main function/thread.
Instead write functions and think step by step algorithmically first.
The simple algorithm to solve this problem can be like this:
1) Generate numbers consecutively starting from 2 which is the least prime, to 13195/2. (Any number always has its factor smaller than half of it's value)
2) Check if the generated number is prime.
3) If the number is prime then check if it is factor of 13195;
4) Return the last prime factor as it is going to be the largest prime factor of 13195;
One more advice is try writting seperate functions to avoid code complexity.
Code is like this...
public class LargestPrimeFactor {
public static long getLargestPrimeFactor(long num){
long largestprimefactor = 0;
for(long i = 2; i<=num/2;i++){
if(isPrime(i)){
if(num%i==0){
largestprimefactor = i;
System.out.println(largestprimefactor);
}
}
}
return largestprimefactor;
}
public static boolean isPrime(long num){
boolean prime=false;
int count=0;
for(long i=1;i<=num/2;i++){
if(num%i==0){
count++;
}
if(count==1){
prime = true;
}
else{
prime = false;
}
}
return prime;
}
public static void main(String[] args) {
System.out.println("Largest prime factor of 13195 is "+getLargestPrimeFactor(13195));
}
}

Categories

Resources