3
\$\begingroup\$

I'm trying to learn Java, so I'm doing a few exercises from a programmer project idea book. This exercise requires that the program be able to convert a decimal number to binary and vice versa, like so:

Please enter the binary/decimal number to convert:9783569
100101010100100100010001

Please enter the binary/decimal number to convert:100101010100100100010001
9783569

Here's the code I came up with:

import java.util.Scanner;

public class BinaryToDecimalAndBackConverter{

    static String convertDecimalToBinary(String decimal){
            int integer = Integer.valueOf(decimal);
            String result = new String();

            while(integer > 0){
                result+=String.valueOf(integer%2);
                integer/=2;
            }

            result = new StringBuffer(result).reverse().toString();
            return result;
    }
    static int convertBinaryToDecimal(String binary){
            int result = 0;

            for(int reverseCounter = 0; reverseCounter < binary.length(); reverseCounter++){
                char currentChar = binary.charAt(binary.length() - reverseCounter - 1);
                int numericValue = Character.getNumericValue(currentChar);
                result+=Math.pow(2, reverseCounter) * numericValue;
//              System.out.println(Math.pow(2, reverseCounter) * Character.getNumericValue(binary.charAt(binary.length() - reverseCounter - 1)) + " reverseCounter " + reverseCounter);
            }

            return result;
    }
    static String isDecimalOrBinary(String input){
        for(int counter = 0; counter < input.length(); counter++){
            if(input.charAt(counter) != '0' && input.charAt(counter) != '1'){
                return "decimal";
            }
        }

        return "binary";
    }
    public static void main(String[] args){
        Scanner inputScanner = new Scanner(System.in);

        System.out.print("Please enter the binary/decimal number to convert:");
        String input = inputScanner.nextLine();

        switch(isDecimalOrBinary(input)){
            case "decimal":
                System.out.println(convertDecimalToBinary(input));
            break;
            case "binary":
                System.out.println(convertBinaryToDecimal(input));
            break;
        }
    }
}
\$\endgroup\$
2
\$\begingroup\$

In addition to @Francesco Pitzalis's answer...

String concatenation

String result = new String();

This is never required as Strings are immutable in Java. If you find yourself using it to append String values, then you should be using StringBuilder (the faster, non-synchronized version of StringBuffer, which is usually recommended unless you require the multi-threading safety of the latter):

StringBuilder result = new StringBuilder();
// ...
result.append(integer % 2); // add some spaces for readability
// ...
return result.reverse().toString();

try-with-resources

// don't forget to close the Scanner
inputScanner.close();

Since you are on Java 7 at least (from the use of String in switch), you should be using try-with-resources to safely and efficiently manage the underlying I/O resource used by your Scanner instance:

try (Scanner scanner = new Scanner(System.in)) {
    // ...
}

Choices and enums

On a related note to your isDecimalOrBinary() method (which @Francesco Pitzalis's answer made a very good point), the return type can also be modeled as an enum should you still choose to keep it:

enum ValueType {
    DECIMAL, BINARY;

    public static ValueType parse(String value) {
        // ...
    }
}

This eliminates the possibility of typos in your expected String return values, e.g. when you return "decimal" but are wrongly checking for "Decimal" from calling the method.

\$\endgroup\$
  • 1
    \$\begingroup\$ Code review never fails to teach me more about Java :). Thanks for your answer, especially for the try-with-resources part. \$\endgroup\$ – Sky Jan 19 '16 at 4:26
2
\$\begingroup\$

The best way to do it:

static String convertDecimalToBinary(String decimal) {
    return Integer.toString(Integer.parseInt(decimal, 10), 2);
}

static int convertBinaryToDecimal(String binary) {
    return Integer.parseInt(binary, 2);
}

By the way your code looks good except for at least two issues:

  1. Don't work with negative numbers
  2. The method isDecimalOrBinary is ambiguous: what's the result of the 100 input? It's binary of course, but if i meant one hundred? I suggest to delegate the user to specify it.

I would correct it in this way:

import java.util.Scanner;

public class BinaryToDecimalAndBackConverter {

    static String convertDecimalToBinary(String decimal) {
        final boolean isNegative = decimal.startsWith("-");
        if (isNegative) {
            decimal = decimal.substring(1);
        }

        int integer = Integer.valueOf(decimal);
        String result = new String();

        while (integer > 0) {
            result += String.valueOf(integer % 2);
            integer /= 2;
        }

        // use StringBuilder instead of StringBuffer, we are sure about
        // exclusive access, no need to use a thread safe class
        final StringBuilder resultBuilder = new StringBuilder(result);
        if (isNegative) {
            resultBuilder.append("-");
        }

        return resultBuilder.reverse().toString();
    }

    static int convertBinaryToDecimal(String binary) {
        final boolean isNegative = binary.startsWith("-");
        if (isNegative) {
            binary = binary.substring(1);
        }
        int result = 0;

        for (int reverseCounter = 0; reverseCounter < binary.length(); reverseCounter++) {
            final char currentChar = binary.charAt(binary.length() - reverseCounter - 1);
            final int numericValue = Character.getNumericValue(currentChar);
            result += Math.pow(2, reverseCounter) * numericValue;
            // System.out.println(Math.pow(2, reverseCounter) *
            // Character.getNumericValue(binary.charAt(binary.length() -
            // reverseCounter - 1)) + " reverseCounter " + reverseCounter);
        }

        if (isNegative) {
            result = -result;
        }

        return result;
    }

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

        System.out.print("Please enter the binary/decimal number to convert:");
        // expected input: NUM D|B
        final String[] splittedInput = inputScanner.nextLine().split(" ");
        if (splittedInput.length != 2) {
            // don't forget to close the Scanner
            inputScanner.close();
            throw new IllegalArgumentException("Wrong input format: expected NUM D|B");
        }
        final String input = splittedInput[0];

        switch (splittedInput[1]) {
        case "d":
        case "D":
            System.out.println(convertDecimalToBinary(input));
            break;
        case "b":
        case "B":
            System.out.println(convertBinaryToDecimal(input));
            break;
        default:
            // don't forget to close the Scanner
            inputScanner.close();
            throw new IllegalArgumentException(
                    "Wrong input format: expected NUM D|B, the second argument was not D nor B");
        }

        // don't forget to close the Scanner
        inputScanner.close();
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ I didn't even consider the 100 case, so thanks for catching it and the unclosed scanner for me :). If only I had known how easy it is to convert the different number systems...I need to read more documentation. If no other answer come up, I'll accept this one :) \$\endgroup\$ – Sky Jan 18 '16 at 17:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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