9
\$\begingroup\$

I have completed my homework with directions as follows:

Declare and implement a class named Binary. This class will have a method named printB(int n) that prints all binary strings of length n. For n = 3, it will print

000
001
010
011
100
101
110
111

in this order.

Is there any way to make this shorter or more efficient?

import java.util.Scanner;
class Binary
{

    String B;
    int temp;

    void printB(int n)
    {
        for(int i = 0; i < Math.pow(2,n); i++)
        {
            B = "";
            int temp = i;
            for (int j = 0; j < n; j++)
            {
                if (temp%2 == 1)
                    B = '1'+B;
                else
                    B = '0'+B;
                    temp = temp/2;
            }
            System.out.println(B);
         }
    } 
}

class Runner
{
    public static void main(String [] args)
    {
        Scanner in = new Scanner(System.in);

        System.out.print("Enter n:");
        int n = in.nextInt();

        Binary myB = new Binary();

        myB.printB(n);
    }
}
\$\endgroup\$
3
\$\begingroup\$

Is there any way to make this shorter or more efficient?

Yes, we can do some things.

for(int i = 0; i < Math.pow(2,n); i++)

You calculate the pow for every iteration. The pow call takes some time (compared to basic things like multiplication or addition), you should do it only once.

B = "";
B = '1'+B;
B = '0'+B;

You will create a lot of string copies for every string concatenation. This costs a lot of perfomance. In general, you should use a StringBuilder.
In this special case, we could even use a char array.

for(int i = 0; i < Math.pow(2,n); i++)
if (temp%2 == 1)
temp = temp/2;

You could use bit manipulations. But depending on the jvm or hotspot compiler, this will be done anyway.

void printB(int n)
        B = "";
        int temp = i;

Overall point: avoid abbreviations.


All together, it could be like this:

void printAllBinaryUpToLength(final int length) {
    if (length >= 63)
        throw new IllegalArgumentException("Current implementation supports only a length < 63. Given: " + length);
    final long max = 1 << length;
    for (long i = 0; i < max; i++) {
        long currentNumber = i;
        final char[] buffer = new char[length];
        int bufferPosition = buffer.length;
        while (bufferPosition > 0) {
            buffer[--bufferPosition] = (char) (48 + (currentNumber & 1));
            currentNumber >>>= 1;
        }
        System.out.println(buffer);
    }
}

Calculates (without printing, printing takes the great majority of every loop) results up to 25 (2^25 = ~33*10^6) in less than a second. Should be enough.

\$\endgroup\$
3
  • \$\begingroup\$ You should explain what the magic number 48 means. Or better yet, avoid it by writing '0'. \$\endgroup\$ – Roland Illig Mar 30 '19 at 20:31
  • \$\begingroup\$ It seems regressive that your code has a maximum length while OP's doesn't. \$\endgroup\$ – Quelklef Mar 31 '19 at 10:38
  • \$\begingroup\$ It has the same restriction as the original specification, namely a maximum amount of last power of two before max integer. In the original specification, this bound is introduced by Math.pow(2,n). In the case of a specification that requires a larger bound, we may switch to longor BigInteger. However, we may also use a simple recursive approach where the bound is only given by the stack depth (or the time of life). \$\endgroup\$ – tb- Sep 2 '19 at 16:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.