0

I have a program that prompts the user for a string, an initial base, and a final base. The program works fine for all digits however, when I enter in a string mixed with digits and characters it does not return the correct answer. For example, when I input the string BDRS7OPK48DAC9TDT4, original base: 30, newBase: 36, it should return ILOVEADVANCEDJAVA, but instead I get ILOVEADVANHSC6LTS. I know it's a problem with my algorithm but I cant figure out why it's returning the incorrect conversion.

import java.util.Scanner;

public class BaseConversion {
    public static void main(String[] args) {

        Scanner s = new Scanner(System.in);
        String theValue;
        String result; 
        String newNum;
        int initialBase;
        int finalBase;
        String[] parts = args;
        if (parts.length > 0) {
            theValue = parts[0];
            isValidInteger(theValue);
            initialBase = Integer.parseInt(parts[1]);
            finalBase= Integer.parseInt(parts[2]);
            isValidBase(finalBase);
       }
       else {
            System.out.println("Please enter a value: ");
            theValue = s.nextLine();
            isValidInteger(theValue);
            System.out.println("Please enter original base: ");
            initialBase = s.nextInt();
            System.out.println("Please enter new base: ");
            finalBase = s.nextInt();
            isValidBase(finalBase);
       }
        // check it
       // isValidInteger(theValue, finalBase);
        s.close();
        newNum = convertInteger(theValue, initialBase, finalBase);


        System.out.println("new number: " + newNum);
    }

    public static void isValidBase(int finalBase) {
        if (finalBase < 2 || finalBase > 36) {
            System.out.println("Error: Base must be greater than or equal to 2 & less than or equal to 36");
            System.exit(1);
        }
    }

    public static void isValidInteger(String num) {
        char chDigit;
        num = num.toUpperCase();
        for(int d = 0; d < num.length(); d++) {
            chDigit = num.charAt(d);
            if (!Character.isLetter(chDigit) && !Character.isDigit(chDigit)) {
                //System.out.println(chDigit);
                System.out.println("Error character is not a letter or number");
                System.exit(1);
            }
        }
    }

    public static String convertInteger(String theValue, int initialBase, int finalBase) {

        double val = 0;
        double decDigit = 0;
        char chDigit;


        // loop through each digit of the original number
        int L = theValue.length();
        for(int p = 0; p < L; p++) {

            // get the digit character (0-9, A-Z)
            chDigit = Character.toUpperCase(theValue.charAt(L-1-p));

            // get the decimal value of our character
            if(Character.isLetter(chDigit)) {
                decDigit = chDigit - 'A' + 10;
            }
            else if (Character.isDigit(chDigit)) {
                decDigit = chDigit - '0';
            }
            else {
                System.out.println("Error d");
                System.exit(1);
            }
            // add value to total
            val += decDigit * Math.pow(initialBase, p);
        }

        // determine number of digits in new base
        int D = 1;

        for( ; Math.pow(finalBase, D) <= val; D++) {}

        // use char array to hold new digits
        char[] newNum = new char[D];

        double pwr; 
        for(int p = D-1; p >= 0; p--) {

            // calculate the digit for this power of newBase
            pwr = Math.pow(finalBase, p);

            decDigit = Math.floor(val / pwr);

            val -= decDigit*pwr;

            // store the digit character

            if(decDigit <= 9) {
                newNum[D - 1 - p] = (char) ('0' + (int)decDigit);
            }
            else {
                newNum[D - 1 - p] = (char) ('A' + (int)(decDigit - 10));
            }
        }       
        return new String(newNum);
    } 
}
Austin Johnson
  • 697
  • 11
  • 23
  • 3
    https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ – shmosel Mar 08 '18 at 18:51
  • Guava has BaseEncoding classes. I would suggest using this instead of hand rolling your own. Check out StandardBaseEncoding in https://github.com/google/guava/blob/master/guava/src/com/google/common/io/BaseEncoding.java – jontro Mar 08 '18 at 23:06

2 Answers2

1

The algorithm is correct. Take a closer look instead at the place where you convert the input value to a decimal system and in particular at the limitations of the data type you are using.

Resources that could be helpful:

  1. primitive data types - double point in the list
  2. Floating point arithmetic
  3. Question concerning similar problem
  4. JLS - 4.2.3. Floating-Point Types, Formats, and Values

Hope this points you to the right track.

kamarius
  • 21
  • 4
0
import java.math.BigInteger;
import java.util.Scanner;

public class BaseConversion {
    public static void main(String[] args) {

        Scanner s = new Scanner(System.in);
        String theValue;
        String result; 
        String newNum;
        int initialBase;
        int finalBase;
        String[] parts = args;
        if (parts.length > 0) {
            theValue = parts[0];
            isValidInteger(theValue);
            initialBase = Integer.parseInt(parts[1]);
            finalBase= Integer.parseInt(parts[2]);
            isValidBase(finalBase);
       }
       else {
            System.out.println("Please enter a value: ");
            theValue = s.nextLine();
            isValidInteger(theValue);
            System.out.println("Please enter original base: ");
            initialBase = s.nextInt();
            System.out.println("Please enter new base: ");
            finalBase = s.nextInt();
            isValidBase(finalBase);
       }
        // check it
       // isValidInteger(theValue, finalBase);
        s.close();
        newNum = convertInteger(theValue, initialBase, finalBase);


        System.out.println("new number: " + newNum);
    }

    public static void isValidBase(int finalBase) {
        if (finalBase < 2 || finalBase > 36) {
            System.out.println("Error: Base must be greater than or equal to 2 & less than or equal to 36");
            System.exit(1);
        }
    }

    public static void isValidInteger(String num) {
        char chDigit;
        num = num.toUpperCase();
        for(int d = 0; d < num.length(); d++) {
            chDigit = num.charAt(d);
            if (!Character.isLetter(chDigit) && !Character.isDigit(chDigit)) {
                //System.out.println(chDigit);
                System.out.println("Error character is not a letter or number");
                System.exit(1);
            }
        }
    }


    public static String convertInteger(String theValue, int initialBase, int finalBase) {
        BigInteger bigInteger = new BigInteger(theValue,initialBase);
        String value = bigInteger.toString(finalBase);
        value = value.toUpperCase();
        return value;
    }
}

Here is the correct solution. The problem was with the data type not the algorithm. I hope this helps anyone dealing with the same type of problem.

Austin Johnson
  • 697
  • 11
  • 23