Java:使用自定义符号在基之间进行转换

时间:2018-07-18 04:02:11

标签: java base

我想知道您是否可以使用自己的符号创建自定义基础,而不是使用Integer.parseInt0-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"
    }
}

我不确定如何执行此操作。有人有代码吗?

2 个答案:

答案 0 :(得分:1)

要执行此操作,您需要首先以from为基础解析输入文本,然后以to为基础格式化值,就像使用标准基础“字母”。

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

因此,首先实现parsetoString,然后实现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

答案 1 :(得分:0)

让我们从值类型开始。它包含一个字符串表示形式和一个Base对象。 (即,它具有字符串表示形式和类似解码器的名称)。为什么?因为我们不想传递需要查看的字符串并“猜测”它们的基础。

public class CustomNumber {
    private final String stringRepresentation;
    private final Base base;
    public CustomNumber(String stringRepresentation, Base base) {
        super();
        this.stringRepresentation = stringRepresentation;
        this.base = base;
    }


    public long decimalValue() {
        return base.toDecimal(stringRepresentation);
    }
    public CustomNumber toBase(Base newBase) {
        long decimalValue = this.decimalValue();
        String stringRep = newBase.fromDecimal(decimalValue);
        return new CustomNumber(stringRep, newBase);
    }
}

然后,我们需要定义一个足够宽的接口,以处理任何常规或自定义符号基。稍后我们将在顶部构建具体的实现。

public interface Base {
        public long toDecimal(String stringRepresentation);
        public String fromDecimal(long decimalValue);
}

我们都准备好了。让我们做一个示例实现,以在使用自定义字符串符号之前支持标准的十进制数字格式:

public class StandardBaseLong implements Base{
    public long toDecimal(String stringRepresentation) {
        return Long.parseLong(stringRepresentation);
    }

    public String fromDecimal(long decimalValue) {
        return Long.toString(decimalValue);
    }
}

现在终于到了自定义字符串库:

public class CustomBase implements Base{
    private String digits;
    public CustomBase(String digits) {
        this.digits = digits;
    }

    public long toDecimal(String stringRepresentation) {
        //Write logic to interpret that string as your base
        return 0L;
    }

    public String fromDecimal(long decimalValue) {
        //Write logic to generate string output in your base format
        return null;
    }
}

现在,您有了一个可以使用各种自定义和标准库的框架。

当然,可能会有更多的自定义和改进的功能(更多的便利构造函数,hashCode和equals实现和算法)。但是,它们超出了此答案的范围。