我想知道您是否可以使用自己的符号创建自定义基础,而不是使用Integer.parseInt
(0-9
和A-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"
}
}
我不确定如何执行此操作。有人有代码吗?
答案 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);
}
因此,首先实现parse
和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
答案 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实现和算法)。但是,它们超出了此答案的范围。