首页 > 解决方案 > Java:使用自定义符号在基数之间进行转换

问题描述

我想知道您是否可以使用自己的符号创建自定义基础,而不是使用Integer.parseInt(0-9A-P.)应用于您的 Java

我在想这样的事情:

public class Base {
    private String symbols;
    public Base(String symbols) {
        this.symbols = symbols;
    }
    // for example: new Base("0123456789"); would represent base 10
    public static String convertBases(Base from, Base to, String toConvert) {
        // Takes toConvert which is encoded in base "from" and converts it to base "to"
    }
}

我不确定如何实现这一点。有没有人有这个的代码?

标签: javabase

解决方案


为此,您需要首先解析基础中的输入文本from,然后格式化基础中的值to,就像使用标准基础“字母表”时需要做的那样。

public static String convertBases(int fromRadix, int toRadix, String text) {
    int value = Integer.parseInt(text, fromRadix);
    return Integer.toString(value, toRadix);
}

所以,首先你实现parseand toString,然后实现convertTo很容易:

public class Base {
    private final String symbols;
    private final BigInteger radix;
    private final Map<Character, Integer> symbolIndex;
    public Base(String symbols) {
        if (symbols.length() <= 1)
            throw new IllegalArgumentException("Must provide at least 2 symbols: length=" + symbols.length());
        this.symbols = symbols;
        this.radix = BigInteger.valueOf(symbols.length());
        this.symbolIndex = new HashMap<>(symbols.length() * 4 / 3 + 1);
        for (int i = 0; i < symbols.length(); i++) {
            Integer prevIndex = this.symbolIndex.putIfAbsent(symbols.charAt(i), i);
            if (prevIndex != null)
                throw new IllegalArgumentException("Duplicate symbol at index " + prevIndex +
                                                   " and " + i + ": " + symbols.charAt(i));
        }
    }
    public BigInteger parse(String text) {
        BigInteger value = BigInteger.ZERO;
        for (int i = 0; i < text.length(); i++) {
            Integer index = this.symbolIndex.get(text.charAt(i));
            if (index == null)
                throw new IllegalArgumentException("Not a valid number: " + text);
            value = value.multiply(this.radix).add(BigInteger.valueOf(index));
        }
        return value;
    }
    public String toString(BigInteger value) {
        if (value.signum() < 0)
            throw new IllegalArgumentException("Negative value not allowed: " + value);
        if (value.signum() == 0)
            return this.symbols.substring(0, 1);
        StringBuilder buf = new StringBuilder();
        for (BigInteger v = value; v.signum() != 0; v = v.divide(this.radix))
            buf.append(this.symbols.charAt(v.mod(this.radix).intValue()));
        return buf.reverse().toString();
    }
    public String convertTo(Base newBase, String text) {
        return newBase.toString(parse(text));
    }
}

测试

Base base3 = new Base("012");
Base base6alpha = new Base("ABCDEF");
System.out.println(base3.convertTo(base6alpha, "0"));   // 0  -> A
System.out.println(base3.convertTo(base6alpha, "2"));   // 2  -> C
System.out.println(base3.convertTo(base6alpha, "10"));  // 3  -> D
System.out.println(base3.convertTo(base6alpha, "200")); // 18 -> DA

输出

A
C
D
DA

测试 2

Base obscure = new Base("^JsdloYF9%");
Base base64 = new Base("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
BigInteger value = new BigInteger("123456789012345678901234567890"); // Too large for int and long
String obscureValue = obscure.toString(value);
String base64Value = base64.toString(value);

System.out.println(obscureValue);
System.out.println(base64Value);
System.out.println(base64.convertTo(obscure, base64Value));
System.out.println(obscure.convertTo(base64, obscureValue));

输出

JsdloYF9%^JsdloYF9%^JsdloYF9%^
BjukP9sNz4O5OPwrS
JsdloYF9%^JsdloYF9%^JsdloYF9%^
BjukP9sNz4O5OPwrS

推荐阅读