Search code examples
androidkotlinerror-handlingdata-conversion

I am getting a String where an Int value should go


I am writing a program to convert any base number to any base and it seems like a lot of the code passes with the user input, but all of a sudden something unexpected happens where the value in decimalNumber is trying to add an empty string, when it cannot do that. Here is the code:

package converter
import kotlin.system.exitProcess
import java.math.BigInteger
import java.util.Scanner
var alphabet = listOf("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")

fun convertNumberToDecimal(numberToConvert: String, sourceBase: Int): BigInteger { // fix this formula!
  var finalValue = ""
  var elementHolder = (numberToConvert).toMutableList()
  var i = elementHolder.size - 1
  var j = 0
  var decimalNumber = 0.toBigInteger()
  while (j != elementHolder.size) {
    if (elementHolder[j].toString().toUpperCase() in alphabet) {
      elementHolder[j] = (10 + alphabet.indexOf(elementHolder[j].toString())).toChar()
      println(elementHolder[j])
    }
    decimalNumber += (elementHolder[j].toString().toBigInteger() * Math.pow(sourceBase.toDouble(), i.toDouble()).toInt().toBigInteger())
    j++
    i--
  }
  return decimalNumber
}

fun convertDecimalToNewBase(numberToConvert: String, targetBase: Int): Any {
  var checker = 0
  var i = 0
  var power = targetBase
  var sumOfNumbers = 0
  var decimalNumber = numberToConvert.toInt()
  var quotient: String = ""
  var remainder = 0
  var listOfNumbers: MutableList<String> = mutableListOf()
  var finalValue = ""
  var denominator = 0
  
  while (checker < numberToConvert.toInt()) {
    checker = Math.pow(targetBase.toDouble(), i.toDouble()).toInt()
    i++
    if (checker > numberToConvert.toInt()) {
      i -= 2
      checker = Math.pow(targetBase.toDouble(), i.toDouble()).toInt()
      break
    }
  }
  
  while (i != -1) {
    denominator = Math.pow(targetBase.toDouble(), i.toDouble()).toInt()
    remainder = (decimalNumber % denominator)
    quotient = (decimalNumber / denominator).toString()
    if (quotient.toInt() >= 10 && quotient.toInt() <= 36 && targetBase > 10) {
      quotient = alphabet[(quotient.toInt() - 10)]
    }
    listOfNumbers.add(quotient)
    decimalNumber = remainder
    i--
  }
    
  for (each in listOfNumbers) {
    finalValue += each.toString()
  }
  for (each in alphabet) {
    if (each in finalValue) {
      return finalValue
    }
  }
  return finalValue.toBigInteger()
}

fun main() {
  var scanner = Scanner(System.`in`)
  println("Enter two numbers in format: {source base} {target base} (To quit type /exit) ")
  var choice = readLine()!!.toString()
  var splitter = listOf<String>()
  var sourceBase: Int
  var targetBase: Int
  var numberInSourceBase: Any
  var newDecimalNumber: Any
  if (choice == "/exit") {
    exitProcess(0)
  } else {
    splitter = choice.split(" ")
    sourceBase = splitter[0].toInt()
    targetBase = splitter[1].toInt()
  }
  do {
    println("Enter number in base " + sourceBase + " to convert to base " + targetBase + " (To go back type /back) ")
    numberInSourceBase = readLine()!!.toString()
    if (numberInSourceBase == "/back") {
      main()
    }
    if (sourceBase != 10) {
      newDecimalNumber = convertNumberToDecimal(numberInSourceBase.toString(), sourceBase)
      newDecimalNumber = (convertDecimalToNewBase(newDecimalNumber.toString(), targetBase)).toString()
    } else {
      newDecimalNumber = (convertDecimalToNewBase(numberInSourceBase.toString(), targetBase)).toString()
    }
    println("Conversion result: " + newDecimalNumber)
  } while (numberInSourceBase != "/back")
}

This is the error message I recieve (Below the error message is user input):

Exception in test #4

java.lang.NumberFormatException: For input string: "    "
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:654)
    at java.base/java.math.BigInteger.<init>(BigInteger.java:536)
    at java.base/java.math.BigInteger.<init>(BigInteger.java:674)
    at converter.MainKt.convertNumberToDecimal(Main.kt:18)
    at converter.MainKt.main(Main.kt:93)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt:90)
    at converter.MainKt.main(Main.kt)

Please find below the output of your program during this failed test.
Note that the '>' character indicates the beginning of the input line.

---

[last 250 lines of output are shown, 56 skipped]
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 2 29
Enter number in base 2 to convert to base 29 (To go back type /back) 
> 1010011110
Conversion result: N3
Enter number in base 2 to convert to base 29 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 2 32
Enter number in base 2 to convert to base 32 (To go back type /back) 
> 1111000101
Conversion result: U5
Enter number in base 2 to convert to base 32 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 2 35
Enter number in base 2 to convert to base 35 (To go back type /back) 
> 1010010111
Conversion result: IX
Enter number in base 2 to convert to base 35 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 2
Enter number in base 5 to convert to base 2 (To go back type /back) 
> 11243
Conversion result: 1100110111
Enter number in base 5 to convert to base 2 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 8
Enter number in base 5 to convert to base 8 (To go back type /back) 
> 3021
Conversion result: 602
Enter number in base 5 to convert to base 8 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 11
Enter number in base 5 to convert to base 11 (To go back type /back) 
> 1213
Conversion result: 157
Enter number in base 5 to convert to base 11 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 14
Enter number in base 5 to convert to base 14 (To go back type /back) 
> 4310
Conversion result: 2D6
Enter number in base 5 to convert to base 14 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 17
Enter number in base 5 to convert to base 17 (To go back type /back) 
> 3242
Conversion result: 195
Enter number in base 5 to convert to base 17 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 20
Enter number in base 5 to convert to base 20 (To go back type /back) 
> 10130
Conversion result: 1D5
Enter number in base 5 to convert to base 20 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 23
Enter number in base 5 to convert to base 23 (To go back type /back) 
> 3213
Conversion result: IJ
Enter number in base 5 to convert to base 23 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 26
Enter number in base 5 to convert to base 26 (To go back type /back) 
> 4214
Conversion result: LD
Enter number in base 5 to convert to base 26 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 29
Enter number in base 5 to convert to base 29 (To go back type /back) 
> 3403
Conversion result: GE
Enter number in base 5 to convert to base 29 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 32
Enter number in base 5 to convert to base 32 (To go back type /back) 
> 3143
Conversion result: D7
Enter number in base 5 to convert to base 32 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 5 35
Enter number in base 5 to convert to base 35 (To go back type /back) 
> 1403
Conversion result: 6I
Enter number in base 5 to convert to base 35 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 2
Enter number in base 8 to convert to base 2 (To go back type /back) 
> 637
Conversion result: 110011111
Enter number in base 8 to convert to base 2 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 5
Enter number in base 8 to convert to base 5 (To go back type /back) 
> 701
Conversion result: 3244
Enter number in base 8 to convert to base 5 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 11
Enter number in base 8 to convert to base 11 (To go back type /back) 
> 773
Conversion result: 421
Enter number in base 8 to convert to base 11 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 14
Enter number in base 8 to convert to base 14 (To go back type /back) 
> 1623
Conversion result: 495
Enter number in base 8 to convert to base 14 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 17
Enter number in base 8 to convert to base 17 (To go back type /back) 
> 267
Conversion result: AD
Enter number in base 8 to convert to base 17 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 20
Enter number in base 8 to convert to base 20 (To go back type /back) 
> 500
Conversion result: G0
Enter number in base 8 to convert to base 20 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 23
Enter number in base 8 to convert to base 23 (To go back type /back) 
> 1063
Conversion result: 11B
Enter number in base 8 to convert to base 23 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 26
Enter number in base 8 to convert to base 26 (To go back type /back) 
> 57
Conversion result: 1L
Enter number in base 8 to convert to base 26 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 29
Enter number in base 8 to convert to base 29 (To go back type /back) 
> 705
Conversion result: FI
Enter number in base 8 to convert to base 29 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 32
Enter number in base 8 to convert to base 32 (To go back type /back) 
> 254
Conversion result: 5C
Enter number in base 8 to convert to base 32 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 8 35
Enter number in base 8 to convert to base 35 (To go back type /back) 
> 455
Conversion result: 8L
Enter number in base 8 to convert to base 35 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 11 2
Enter number in base 11 to convert to base 2 (To go back type /back) 
> 143
Conversion result: 10101000
Enter number in base 11 to convert to base 2 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 11 5
Enter number in base 11 to convert to base 5 (To go back type /back) 
> 123
Conversion result: 1041
Enter number in base 11 to convert to base 5 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 11 8
Enter number in base 11 to convert to base 8 (To go back type /back) 
> 451
Conversion result: 1034
Enter number in base 11 to convert to base 8 (To go back type /back) 
> /back
Enter two numbers in format: {source base} {target base} (To quit type /exit) 
> 11 14
Enter number in base 11 to convert to base 14 (To go back type /back) 
> 272
Conversion result: 18D
Enter number in base 11 to convert to base 14 (To go back type /back) 
> /back
Enter two numbers in forma

The Number Format Exception is coming from this line of code:

decimalNumber += (elementHolder[j].toString().toBigInteger() * Math.pow(sourceBase.toDouble(), i.toDouble()).toInt().toBigInteger())

Solution

  • You can avoid the error in the convertNumberToDecimal function by try-catching the string conversion:

    fun convertNumberToDecimal(numberToConvert: String, sourceBase: Int): BigInteger { 
        var finalValue = ""
        var elementHolder = (numberToConvert).toMutableList()
        var i = elementHolder.size - 1
        var j = 0
        var decimalNumber = 0.toBigInteger()
        while (j != elementHolder.size) {
            try {
              if (elementHolder[j].toString().toUpperCase() in alphabet) {
                elementHolder[j] = (10 + alphabet.indexOf(elementHolder[j].toString())).toChar()
                println(elementHolder[j])
              }
              decimalNumber += (elementHolder[j].toString().toBigInteger() * Math.pow(sourceBase.toDouble(), i.toDouble()).toInt().toBigInteger())
            } catch (e: NumberFormatException) { }
          j++
          i--
        }
        return decimalNumber
      }
    

    However, given the structure of your program, I think that the error may be related to incorrect input.
    By splitting the input string (line splitter = choice.split(" ")) you are not considering strings with multiple spaces.
    In that case, an empty string will be passed to the function, which will throw an exception.
    You could prevent the error by filtering the inputted string:

    splitter = choice.split(" ").filter { it != "" }
    if (splitter.size != 2) {
        // Malformed string
        exitProcess(0)
    }
    sourceBase = splitter[0].toInt()
    targetBase = splitter[1].toInt()