-2

Question prompt: Modify Binary to get a program that takes two integer command-line arguments i and k and converts i to base k. Assume that i is an integer in Java’s long data type and that k is an integer between 2 and 16. For bases greater than 10, use the letters A through F to represent the 11th through 16th digits, respectively.

I have managed to convert decimals to base 2-10 successfully, but I can't seem to convert decimals with the inclusion of the characters A through F that represents the 11th to 16th digits, respectively.

I don't want to use any arrays or lists. I understand my switch statement is lacking functionality that would solve my problem, but I'm not sure how to improve it. I'm trying to solve the problem using a switch statement.

In the code, i represents an integer to convert to base k. k represents a base that can be 2-16.

public class BaseConversion
    {
        public static void main(String[] args)
        {
            int i = Integer.parseInt(args[0]);
            int k = Integer.parseInt(args[1]);
            int power = 1;
            while (power <= i/k)
            {
                power *= k;
            }   // Now power is the largest power of k <= i.
            if (k <= 10)
            {
                while (power > 0)
                {
                    int digit = i / power;
                    System.out.print(digit);
                    i -= digit * power;
                    power /= k;
                }
            }
            else if (k > 10)
            {
                switch (k)
                {
                    case 11: System.out.println('A'); break;
                    case 12: System.out.println('B'); break;
                    case 13: System.out.println('C'); break;
                    case 14: System.out.println('D'); break;
                    case 15: System.out.println('E'); break;
                    case 16: System.out.println('F'); break;
                }
            }
        }    
    }
  • Can you elaborate what your input parameters `i` and `k` represent? Maybe some example inputs and expected outputs would be good. Also: Is the code above the one you say already correctly converting decimal to base 2-10? – OH GOD SPIDERS Jan 03 '22 at 14:50
  • i: Integer to convert to base k. k: base represented by an integer between 2 and 16. Yes, the current code is successful when converting decimal to base 2-10. – silicongolem Jan 03 '22 at 14:51
  • 3
    Did you have a look at `Integer.parseInt(String value, int radix)` (radix = base)? – Thomas Jan 03 '22 at 14:52
  • I'm trying to solve the problem using switch statements. – silicongolem Jan 03 '22 at 14:54
  • The switch is in the wrong place. The switch should be deciding what to print, i.e. where you calculate the digit. (Also, switch cases are off by 1, and you shouldn't be switching on k) – Andy Turner Jan 03 '22 at 14:56
  • I have just revised the boolean expressions in the if statements that were wrong where you saw that the switch cases that were off by 1. I'm not sure where to put the switch statement and what to add to the switch statement. – silicongolem Jan 03 '22 at 15:00
  • decimal digits are [0-9] (not [1-10]) ... F in hex means 15 (not 16;) ..16(dec) = 10(hex;) – xerx593 Jan 03 '22 at 15:00
  • I have just added the question prompt that I'm trying to answer and it seems that F is supposed to be represented by 16 because of the prompt. – silicongolem Jan 03 '22 at 15:03

2 Answers2

0

If you need to convert an integer (which is base 10) to any other base using a single switch statement you can use something like this:

int i = //take from CLI
int k = //take from CLI

int num = i; //copy so we still have the original input

//we need a string to represent anything but base-10 integers
StringBuilder sb = new StringBuilder();
    
//decompose the input
while( num > 0 ) {
    //extract the last digit
    int digit = num % k;
        
    //map the digit to a character - note: this is NOT k but the digit we extracted from the input
    switch(digit) {            
        case 0,1,2,3,4,5,6,7,8,9:
            sb.append(digit);
            break;
        case 10:
            sb.append("A");
            break;
        case 11:
            sb.append("B");
            break;
        case 12:
            sb.append("C");
            break;
        case 13:
            sb.append("D");
            break;
        case 14:
            sb.append("E");
            break;
        case 15:
            sb.append("F");
            break;
    }

    //reduce the magnitude of the number by 1, i.e. divide by the base
    num /= k;
}

//we extracted the digits from the back so we need to reverse the string for proper left-to-right output
String result = sb.reverse().toString();

This should get you started. Note that it lacks a couple of checks, e.g. if k is in the range [2,16]. It also works with positive numbers so far but negative input could easily be handled by multiplying the number with -1 and adding the sign to the string buffer before the conversion.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • Thanks for your response. Can you show me how to do this without a StringBuilder as this is more advanced than my current understanding? – silicongolem Jan 03 '22 at 16:27
  • @silicongolem We, you can also just prepend the characters to a string, i.e. `result = "A" + result` etc. – Thomas Jan 03 '22 at 16:51
  • Ok, thank you so much! I am also wondering why the output is always a number before the program converts to base 10-15. – silicongolem Jan 03 '22 at 17:01
  • @silicongolem I'm not sure what exactly you mean. Do you mean why `digit` is an `int` and then converted? That's because we can't calculate with strings, so the input will be converted to a base-10 integer first (if it isn't already base-10). – Thomas Jan 04 '22 at 06:39
  • I was wondering why there is no character such as A through F. – silicongolem Jan 04 '22 at 16:35
  • @silicongolem I'm not sure I understand your comment. If you're refering to why the input always has base 10 then have a look at your question: "Assume that i is an integer in Java’s long data type" - `int` and `long` (and any other built-in numeric types) are base 10. – Thomas Jan 04 '22 at 18:11
  • How would you convert it to a base higher than 16, say 30? – David G May 25 '22 at 17:24
  • @DavidG that depends on what chars you want to use. There are built-in methods like `Integer.toString(int, base)` but if that doesn't suit you you could always roll your own. Just provide a mapping for each of the "modulus results". This could be a simple switch expression similar to the above, a map (int, char) or some form of calculation such as `int digit = n % base; char mapped = digit < 10 ? (char)(digit) : 'a' + digit - 10;` (if your base is higher you might need to map chars from different ranges in which case the calculation could get some more conditions). – Thomas May 30 '22 at 06:32
0

There are several issues in the presented code:

  • negative values are ignored
  • digits in the switch statement should be shifted down by 1: 10 -> a, 11 -> b, .. 15 -> f
  • the conversion to the string is missing, the code is printing digits one by one

So, a StringBuilder should be used to accumulate the result. If the input is negative, minus sign should be appended and the sign is inverted, then the digits are calculated using modulo by k and inserted into the result in reverse order.

private static String convert(long n, int k) {
    assert(2 <= k && k <= 16);
    StringBuilder sb = new StringBuilder();
    int p = 0;
    if (n < 0) {
        sb.append('-');
        n *= -1;
        p = 1;
    }
    while (n > 0) {
        int digit = (int) (n % k);
        n /= k;
        if (digit < 10) {
            sb.insert(p, digit);
        } else {
            sb.insert(p, switch(digit) {
                case 10 -> 'a';
                case 11 -> 'b';
                case 12 -> 'c';
                case 13 -> 'd';
                case 14 -> 'e';
                default -> 'f'; // the only remaining option
            });
        }
    }
    return sb.toString();
}

Similarly, the result may be collected into a String instead of StringBuilder. However, such approach is not recommended generally (string concatenation in a loop):

private static String convert(long n, int k) {
    String s = "";
    String sign = "";
    if (n < 0) {
        sign = "-";
        n *= -1;
    }
    while(n > 0) {
        int digit = (int) (n % k);
        n /= k;
        if (digit < 10) {
            s = digit + s;
        } else {
            s = switch(digit) {
                case 10 -> 'a';
                case 11 -> 'b';
                case 12 -> 'c';
                case 13 -> 'd';
                case 14 -> 'e';
                default -> 'f';
            } + s;
        }
    }
    return sign + s;
}
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42