I'm doing some problems of Project Euler and I've stumbled upon an issue.
I have no idea why this algorithm doesn't work for 2^1000. It works for numbers in the range of 10^1 and 10^8 (Those are the ones I tested), but it should work for every possible range.
2^1000 is 1.07*10^301 by the way. The upper limit of a double lies at more or less 10^308 so the number is still in range.
import java.lang.Math;
public class Euler15 {
public static void main(String[] args) {
int count = 0;
double res = Math.pow(2,1000);
for(int i = 301; i >= 0; i--){
if (res == 0){
break;
}
while (res >= Math.pow(10, i)){
res-= Math.pow(10, i);
System.out.println(res);
count++;
}
}
System.out.println(count);
}
}
2^1000 is way to big for normal data types. Use BigInteger or strings.
import java.math.BigInteger;
Take an input as a BigInteger:
BigInteger n = BigInteger.valueOf(2);
Now power it up to 1000:
n = n.pow(1000);
Now, convert it into a string using toString() and then, add each character to your result, changing it to an int. That ought to do it.
Related
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;
}
}
I've been trying to write a small and simple program that converts dec numbers to bin.The idea is that when the user enters a positive integer a for- cycle have to go through all the rounds of deviding the number /2 but it also have to get the tail (idk the math term really the actuall bin numbers) and write them in an array, thats the part Im having trouble with.I have predefined the array size of 30 (cant find a way to make a working array without specifying it's length) my idea was that then I could make a reversed array with length = index(i from the first for cycle) from the previous array with another for cycle etc. but when I tested the first array all I get is empty brackets printed: [] or nothing at all, eclipse doesnt find any errors in the code and I cant figure out whats wrong.I could use some help.Anyways here's the code:
public static void decToBin(){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
if (n <= 0) {System.out.println("ERROR:n<=0");return;}
else if (n > 0){
int[] ostataci = new int[30];
for (int i = 0;n <= 0;i++){
ostataci[i] = n % 2;
n = n / 2;
// System.out.printf("%d %n", ostataci[i]); - even this one doesnt print at all
}
// System.out.println(Arrays.toString(ostataci)); - nor this one
}
}
Thanks for the replies Ive learnt a few new things.But since Im a newbie I wanted to do it with the metod I described thx for pointing me the error in the for cycle, that was my biggest problem, anyway heres the last code I wrote( working correctly) thats what I was trying to do from the beggining.
public static void decToBin2(){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
int i = 0;
int[] ostataci = new int[32];
if (n <= 0) {System.out.println("ERROR:n<=0");return;}
else if (n > 0){
while (n > 0){
i++;
ostataci[i] = n % 2;
n = n / 2;
}
}
int reverse = i;
int[] reversed = new int[reverse];
for (int i2 = 0;i2 != reverse;i--,i2++){
reversed[i2] = ostataci[i];
System.out.print(reversed[i2]);
}
}
The immediate error is in the for loop:
else if (n > 0) {
// Since n > 0 it'll never run
for (int i = 0;n <= 0;i++)
The implementation itself could be something like that (keep it simpler!):
...
if (n <= 0)
System.out.println("ERROR:n<=0");
else {
// Why do we need array/ArrayList etc.? We are supposed to build a string!
StringBuilder Sb = new StringBuilder();
// while we have something to do...
// (are we supposed to compute exact number of steps? No)
while (n > 0) {
Sb.insert(0, n % 2);
n /= 2;
}
System.out.println(Sb.toString());
}
Your loop for (int i = 0;n <= 0;i++){ } won't execute because you know that n is positive (by your if condition), but the for condition demands that n be negative (n <= 0). I suspect you mean n>0 instead.
As for variable length arrays you can use Lists, although that might be better to add in later
your for loop is wrong for (int i = 0;n <= 0;i++){ this just wont run change it to something like this while (n > 0) { and your code will works fine. also int is 32 bit so change int[] ostataci = new int[30]; to int[] ostataci = new int[32]; although it is better to uselist instead of array.
Decimals are already converted to binary on the computer, why don't you use bit wise operations to check the saved integer? Eg to check if bit n of an int is set, evaluate the boolean (number >> n) & 1. Just put that in a loop and you're done. Everyone else is making it too complicated.
Here is an alternative approach, using the shift operator and bit-masking:
public static int[] dec2bin(int n) {
int[] result = new int[32];
for (int i = 0; i < 32; i++) {
result[31-i] = n & 0x1;
n >>= 1;
}
return result;
}
This will also work just fine for negative numbers.
Example usage:
public static void main(String[] args) {
int[] result = dec2bin(5);
for (int i : result)
System.out.print(i);
System.out.flush();
}
Ouput:
00000000000000000000000000000101
Explaination
The code n & 0x1 from above is bit-masking. The 0x1 is hex notation for the number 1. In binary, that number looks like this:
00000001
In the first iteration of the for loop, n looks like:
00000101
The & operator does a bit-by-bit (bitwise) comparison of the bits in the two numbers, 'anding' them together, producing a new number based on those comparisons. If either or both of the corresponding bits are 0, the resulting bit is 0. If both of them are 1, the resulting bit is 1. So, for the two numbers listed above, the result of 'anding' them together is:
00000001
Or, in decimal, 1. You'll note that that also happens to be the bit value of the rightmost bit in n. Which we save into the result array at the rightmost index.
Next, we shift (>>) n right by 1. This moves every bit along by one (the rightmost bit is lost), and the resulting n is now:
00000010
We repeat that process 32 times (for each of the 32 bits of an int) and at the end we get a result array containing the correct answer.
Try this:
package mypackage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Arrays;
public class Converter{
final static int ARRAY_SIZE = 30;
public static void main(String[] args){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
if (n <= 0){
System.out.println("ERROR:n<=0");
return;
}else if (n > 0){
int[] ostataci = new int[ARRAY_SIZE];
int i = 0;
while (n>0){
ostataci[i] = n % 2;
i++;
n = n / 2;
System.out.printf("%d %n", ostataci[i]);
}
System.out.println("All done!");
System.out.println(Arrays.toString(ostataci));
}
}
}
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 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.
I want to convert decimal numbers to binary numbers. I want to store them in an array.
First I need to create an array that has a certain length so that I can store the binary numbers. After that I perform the conversion, here is how I do it:
public class Aufg3 {
public static void main(String[] args) {
int[] test = decToBin(12, getBinArray(12));
for(int i = 0; i < test.length; i++){
System.out.println(test[i]);
}
}
public static int[] getBinArray(int number){
int res = number, length = 0;
while(res != 0){
res /= 2;
length++;
}
return new int[length];
}
public static int[] decToBin(int number, int[] array){
int res = number, k = array.length-1;
while(res != 0){
if(res%2 == 0){
array[k] = 0;
}else{
array[k] = 1;
}
k--;
res /= 2;
}
return array;
}
}
Is there anything to improve? It should print 1100 for input of 12.
Why not just use the toBinaryString method of the Integer class:
System.out.println(Integer.toBinaryString(12))
I assume you want to write your own code -- otherwise this is straightforward to do using methods from the standard Java library.
Some quick comments:
You can get rid of the res temp vars. Work directly on number (remember that Java passes parameters by value).
Shift is more efficient than division (number >>>= 1 instead of number /= 2), although the compiler should be able to optimize this anyway
You can avoid the modulus in decToBin if you just do array[k] = number & 1;
While you are at it, why not call getBinArray from decToBin directly? Then you can call decToBin with only one arg -- the value to convert.
Here is a slightly optimized version of your code:
public static int[] getBinArray(int number) {
int length = 0;
while (number != 0) {
number >>>= 1;
length++;
}
return new int[length];
}
public static int[] decToBin(int number) {
int[] array = getBinArray(number);
int k = array.length-1;
while (number != 0)
{
array[k--] = number & 1;
number >>>= 1;
}
return array;
}
If this isn't homework, no need to do it yourself. The following code should work:
BigInteger bigInt = new BigInteger(number);
String asString = bigInt.toString(2);
There might be more efficient ways, but this is certainly very readable and maintainable.
There are some small things that you can improve:
You should define a "high-level" method that converts an int to an int[]. In the current code you have to mention the 12 two times, which is bad.
You should use a do { ... } while (number != 0) loop. Otherwise the number 0 will be represented by an empty array.
You should use x >>> 1 instead of x / 2, since that handles negative numbers correctly.
If you want to check that your code is correct, write another method that converts back from binary to int. Then you can check that binToDec(decToBin(12, ...)) == 12.
The method getBinArray should not be public, since it is only a helper method. You can either replace the public with private or just remove the public.