Skip to content

Instantly share code, notes, and snippets.

@ygrenzinger
Created March 5, 2021 20:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ygrenzinger/054605355c0e91b7d114afad1745b6ed to your computer and use it in GitHub Desktop.
Save ygrenzinger/054605355c0e91b7d114afad1745b6ed to your computer and use it in GitHub Desktop.
Number Base Converter
package converter
import java.math.BigDecimal
import kotlin.math.pow
tailrec fun convertFromDecimal(rest: Long, base: Int, result: List<String>): List<String> {
return if (rest < base) {
result + rest.toString(base)
} else {
val remainder = rest % base
val quotient = rest / base
convertFromDecimal(quotient, base, result + remainder.toString(base))
}
}
fun convertFromDecimal(number: Long, base: Int): String {
return convertFromDecimal(number, base, emptyList())
.reversed()
.joinToString("") { it }
}
fun convertFractionalFromDecimal(fractional: BigDecimal, base: Int): String {
val result = mutableListOf<String>()
var remaining = fractional
var precision = 1
while (precision <= 5 && remaining.compareTo(BigDecimal.ZERO) != 0) {
remaining = remaining.multiply(base.toBigDecimal())
val integerPart = remaining.toInt()
if (integerPart > 0) {
result.add(integerPart.toString(base))
remaining = remaining.subtract(integerPart.toBigDecimal())
} else {
result.add("0")
}
precision++
}
return result.joinToString("") { it.toString() }
}
fun convertToDecimal(number: String, base: Int): Long {
return number.toLowerCase().reversed().mapIndexed {
i, c -> (Integer.valueOf(c.toString(), base) * base.toDouble().pow(i)).toLong()
}.sum()
}
fun convertFractionalToDecimal(factional: String, base: Int): BigDecimal {
return factional.toLowerCase().mapIndexed { i, c ->
val number = Integer.valueOf(c.toString(), base)
if (number == 0) {
number.toBigDecimal()
} else {
(number * base.toDouble().pow(-(i+1))).toBigDecimal()
}
}.reduceRight(BigDecimal::add)
}
fun convert(number: String, source: Int, target: Int): String {
return try {
if (number.contains('.')) {
val (integer, fractional) = number.split(".")
val decimalInteger = convertToDecimal(integer, source)
val convertedInteger = convertFromDecimal(decimalInteger, target)
val decimalFractional = convertFractionalToDecimal(fractional, source)
val convertedFractional = convertFractionalFromDecimal(decimalFractional, target)
"$convertedInteger.$convertedFractional"
} else {
val decimal = convertToDecimal(number, source)
convertFromDecimal(decimal, target)
}
} catch (e: Throwable) {
"error when trying to convert $number from base $source to base $target"
}
}
fun convert(source: Int, target: Int) {
while (true) {
print("Enter number in base ${source} to convert to base $target (To go back type /back) ")
val input = readLine()!!
if (input == "/back") {
break
}
if (source == target) {
if (input.contains(".")) {
val (integer, fractional) = input.split(".")
println("Conversion result: $integer.${fractional.substring(0, 5)}")
} else {
println("Conversion result: $input")
}
} else {
val result = convert(input, source, target)
println("Conversion result: $result")
}
println()
}
}
fun main() {
while (true) {
print("Enter two numbers in format: {source base} {target base} (To quit type /exit) ")
val command = readLine()!!
if (command == "/exit") {
break
}
val (source, target) = command.split(" ").map { it.toInt() }
convert(source, target)
}
}
@Falcon8317
Copy link

Great program! But it has some problem:

Enter two numbers in format: {source base} {target base} (To quit type /exit) 2 5
Enter number in base 2 to convert to base 5 (To go back type /back) 1011000100.00000
Conversion result: 10313.
The conversion result is missing zeroes after the decimal point.

@ygrenzinger
Copy link
Author

Thanks. It was only a fun experiment. Don't take this code too seriously :)

@Falcon8317
Copy link

Falcon8317 commented Jan 16, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment