Java 当处理较大的“值”时,此代码有什么错误;长“;?
我编写了一个实用程序类,用base N对自定义的数字进行编码。作为一个自尊的Java程序员,我随后编写了一个单元测试,以检查代码是否按预期工作(对于任何我可以抛出的数字) 事实证明,对于小数字,它是有效的。然而,对于足够大的数量,测试失败了 守则:Java 当处理较大的“值”时,此代码有什么错误;长“;?,java,math,puzzle,Java,Math,Puzzle,我编写了一个实用程序类,用base N对自定义的数字进行编码。作为一个自尊的Java程序员,我随后编写了一个单元测试,以检查代码是否按预期工作(对于任何我可以抛出的数字) 事实证明,对于小数字,它是有效的。然而,对于足够大的数量,测试失败了 守则: public class EncodeUtil { private String symbols; private boolean isCaseSensitive; private boolean useDefaultSy
public class EncodeUtil {
private String symbols;
private boolean isCaseSensitive;
private boolean useDefaultSymbols;
private int[] symbolLookup = new int[255];
public EncodeUtil() {
this(true);
}
public EncodeUtil(boolean isCaseSensitive) {
this.useDefaultSymbols = true;
setCaseSensitive(isCaseSensitive);
}
public EncodeUtil(boolean isCaseSensitive, String symbols) {
this.useDefaultSymbols = false;
setCaseSensitive(isCaseSensitive);
setSymbols(symbols);
}
public void setSymbols(String symbols) {
this.symbols = symbols;
fillLookupArray();
}
public void setCaseSensitive(boolean isCaseSensitive) {
this.isCaseSensitive = isCaseSensitive;
if (useDefaultSymbols) {
setSymbols(makeAlphaNumericString(isCaseSensitive));
}
}
private void fillLookupArray() {
//reset lookup array
for (int i = 0; i < symbolLookup.length; i++) {
symbolLookup[i] = -1;
}
for (int i = 0; i < symbols.length(); i++) {
char c = symbols.charAt(i);
if (symbolLookup[(int) c] == -1) {
symbolLookup[(int) c] = i;
} else {
throw new IllegalArgumentException("duplicate symbol:" + c);
}
}
}
private static String makeAlphaNumericString(boolean caseSensitive) {
StringBuilder sb = new StringBuilder(255);
int caseDiff = 'a' - 'A';
for (int i = 'A'; i <= 'Z'; i++) {
sb.append((char) i);
if (caseSensitive) sb.append((char) (i + caseDiff));
}
for (int i = '0'; i <= '9'; i++) {
sb.append((char) i);
}
return sb.toString();
}
public String encodeNumber(long decNum) {
return encodeNumber(decNum, 0);
}
public String encodeNumber(long decNum, int minLen) {
StringBuilder result = new StringBuilder(20);
long num = decNum;
long mod = 0;
int base = symbols.length();
do {
mod = num % base;
result.append(symbols.charAt((int) mod));
num = Math.round(Math.floor((num-mod) / base));
} while (num > 0);
if (result.length() < minLen) {
for (int i = result.length(); i < minLen; i++) {
result.append(symbols.charAt(0));
}
}
return result.toString();
}
public long decodeNumber(String encNum) {
if (encNum == null) return 0;
if (!isCaseSensitive) encNum = encNum.toUpperCase();
long result = 0;
int base = symbols.length();
long multiplier = 1;
for (int i = 0; i < encNum.length(); i++) {
char c = encNum.charAt(i);
int pos = symbolLookup[(int) c];
if (pos == -1) {
String debugValue = encNum.substring(0, i) + "[" + c + "]";
if (encNum.length()-1 > i) {
debugValue += encNum.substring(i + 1);
}
throw new IllegalArgumentException(
"invalid symbol '" + c + "' at position "
+ (i+1) + ": " + debugValue);
} else {
result += pos * multiplier;
multiplier = multiplier * base;
}
}
return result;
}
@Override
public String toString() {
return symbols;
}
}
你知道为什么当价值变大时事情就开始失败了吗?我也尝试过BigInteger,但似乎没有什么不同。代码中有一个到double的转换,这可能会为大值生成奇怪的结果
num = Math.round(Math.floor((num-mod) / base));
这将是我的第一个调用端口。您的代码中有一个到double的转换,这可能会为大值生成奇怪的结果
num = Math.round(Math.floor((num-mod) / base));
这将是我的第一个调用端口。您在
encodeNumber
方法中使用浮点数学,这使得您的代码依赖于双精度类型的精度
替换
num = Math.round(Math.floor((num-mod) / base));
与
使测试通过。实际上
num = num / base;
应该也行(思维实验:当/
是整数除法时,19/10
是什么?你在encodeNumber
方法中使用浮点数学,这使得你的代码依赖于双精度类型
替换
num = Math.round(Math.floor((num-mod) / base));
与
使测试通过。实际上
num = num / base;
应该同样有效(思考实验:当/
是整数除法时,什么是19/10
。代码的第一个问题是:ASCII没有255个值……更严重的是,你已经给出了很多代码,几乎没有说明你已经研究了什么。例如,您是否尝试确定问题是在编码器还是解码器中?测试用例中的数字是2^60。Long.MAX_值为2^63-1。如果我是你,我会找一个你的数字乘以大约2^3的地方。因为现在的代码很容易失败,而且很难阅读。提示:声称很多很多人一直在使用的语言/库有一个基本的缺陷,就像这个缺陷一样,这是一个很容易获得否决票的方法(至少我猜这就是投票被否决的原因,否则这是一个写得很好的问题)。代码的第一个问题:ASCII没有255个值…更严重的是,您已经提交了很多代码,但几乎没有说明您已经调查过的内容。例如,您是否尝试确定问题是在编码器还是解码器中?测试用例中的数字是2^60。Long.MAX_值是2^63-1。如果我是您,我想找一个你的数字乘以大约2^3的地方。因为代码现在很容易失败,而且很难阅读。提示:声称很多很多人一直使用的语言/库有一个基本缺陷,就像这个缺陷一样,这是一个很容易获得否决票的方法(至少我猜这就是投票被否决的原因,因为否则这是一个写得很好的问题。)还有什么替代方案?还有什么替代方案?