你说的是这段代码:
if (len > 3 && len % 2 == 0) {
len++;
}
这意味着如果 len 大于 3(显然!)并且如果 len 是一个 even 数字。
% 符号用于modulo operation。
维基百科关于模运算的定义是:
在计算中,取模运算求除法后的余数
一个数到另一个数(有时称为模数)。
更新
关于此代码段背后的逻辑。我只会尝试猜测原作者的意图。 len 变量将保存数字的长度。
如果长度小于 100,那么作者将在 } else { // Number is less than 1000 块中创建所需的字符串。如果你看得更清楚这个代码段,len 变量永远不会被使用,除非最后他使它等于 0 以退出循环。
因此,对于 len。
现在,对于大于 1000 的数字,它被使用,我猜作者需要更改它以便将它用于数组访问。这就是使用第 23 到 25 行的原因。因此,对于数字 1000 到 9999 len 是 4,对于 10000 到 99999 len 是 5,对于 100000 到 999999 len 是 6。我猜如果不更改它,作者无法访问所需的数组值。这就是我对为什么使用此代码的猜测。
但是,我猜从给定的字符串中,该方法应该适用于从 0 到 999999 的数字。试试这个想法:
int err = 0;
for(int i = 0;i<999999;i++) {
try {
numtostring(i);
} catch (Exception e){
err++;
}
}
System.out.println(err+" ERORRS");
这将打印900000 ERRORS。它适用于 1000 的情况以及从 100000 到 999999 的所有数字。这两种情况没有从这段代码中正确处理。我发现整个len 操作非常错误且难以理解。我不确定作者是否还有其他想法。
这是一个修订版,它似乎适用于从 0 到 999999 的数字,我发现它更容易理解。
public static String numtostring(int num) {
StringBuilder sb = new StringBuilder();
// Count number of digits in num.
int len = String.valueOf(num).length();
String[] wordarr1 = {"", "One ", "Two ", "Three ", "Four ",
"Five ", "Six ", "Seven ", "Eight ", "Nine "};
String[] wordarr11 = {"", "Eleven ", "Twelve ", "Thirteen ",
"Fourteen ", "Fifteen ", "Sixteen ",
"Seventeen ", "Eighteen ", "Nineteen "};
String[] wordarr10 = {"", "Ten ", "Twenty ", "Thirty ", "Forty ",
"Fifty ", "Sixty ", "Seventy ", "Eighty ",
"Ninety "};
int tmp;
if (num == 0) {
sb.append("Zero");
} else if (num >= 1000000) {
System.err.println("Numbers > 999999 are not supported!");
System.exit(1);
} else {
do {
// Number greater than 999
if (len > 3) {
int n = num / 1000;
sb.append(numtostring(n)).append("Thousand ");
num = num % 1000;
len -= String.valueOf(n).length();
} else { // Number is less than 1000
tmp = num / 100;
if (tmp != 0) {
sb.append(wordarr1[tmp]);
sb.append("Hundred ");
}
tmp = num % 100;
if (tmp / 10 == 1 && tmp % 10 != 0) {
sb.append(wordarr11[tmp % 10]);
} else {
sb.append(wordarr10[tmp / 10]);
sb.append(wordarr1[tmp % 10]);
}
len = 0;
}
} while (len > 0);
}
return sb.toString();
}
您还可以通过再次调用 numtostring() 并以 n 作为参数并将其附加到 sb 来消除 do-while 循环。
无论如何,在使用它之前自己测试一下,以确保我没有忘记任何东西:) 希望对你有所帮助!
更新 2
好的,所以我们讨论的原始方法适用于长度
让我们看看len是如何使用的:
if (len > 3 && len % 2 == 0) {
// if len is 4 it becomes 5, if it is 5 it stays as is
// if len is 6 it becomes 7 and an exception occurs
len++;
}
...
if (len > 3) {
// puts the thousand part in tmp
// so if num is 9000, len is 5 and tmp is 9 (9000/10^3)
// if num is 99000, len is 5 and tmp is 99 (99000/10^3)
// and if num is 999000, len is 7 and tmp is 9 instead of 999 (999000/10^5)
tmp = (num / (int)Math.pow((double)10,(double)len-2));
// If tmp is 2 digit number and not a multiple of 10
// So, if tmp is 11 to 19 (num was 11000 to 19999) it enters the if
if (tmp / 10 == 1 && tmp%10 != 0) {
// if tmp is 11 tmp % 10 is 1 and the wordarr11[1] is eleven etc.
sb.append(wordarr11[tmp % 10]) ;
} else {
// if tmp is not 11 to 19 it enters here
// this means if tmp is 1 to 9 for num 1000 to 9999
// if tmp is 10 for num 10000 to 10999
// if tmp is 20 to 99 for num 20000 to 99999
// if tmp is 100 to 999 for num 100000 to 999999
// wordarr10 contains the dozens
// if tmp is 10 this will be ten, if it is 20 this will be twenty etc.
// if tmp is 1 to 9 tmp / 10 will return 0 and sb will append an empty string (wordarr10[0])
sb.append(wordarr10[tmp / 10]);
// wordarr1 contains the units
// if tmp is 1 to 9 then tmp % 10 will return the tmp as it is
// if tmp is 10 or 20 tmp % 10 will return 0 and append the empty string
// if tmp is 23 tmp % 10 will return 3 and append the word three
sb.append(wordarr1[tmp % 10]);
}
// if tmp is a positive numbers... we know it is but ok...
// we append the word hundrend if len is 2 or three, which is impossible because we are in the if(len > 3) branch
// if original len was 4 it have become 5 earlier so
// if len is 5 the len / 2 is 2 and we append the word thousand
// if len is 7 len / 2 is 3 and an out of bounds exception gets thrown
if (tmp > 0) {
sb.append(wordarr100[len / 2]);
}
// finally we remove the part of num that we have printed in order to print the rest
// so if num is 1123 then it will become 123
// or if it is 12123 it will become again 123 (because len is 5)
// if len is 7 this will fail and for example 123123 will become 23123
num = num % (int)(Math.pow((double)10,(double)len-2));
// if len is 5 then we make it three in order to run the else branch and print the rest part
// if len was 7 this would make it 5 and the same branch would run again which I guess is also wrong
len = len-2;
整个混乱或多或少是由这两行造成的:
tmp = (num / (int)Math.pow((double)10,(double)len-2));
num = num % (int)(Math.pow((double)10,(double)len-2));
他们应该更好地使用1000 而不是(int)Math.pow((double)10,(double)len-2)。那么剩下的部分或多或少会像其他部分一样。请参阅我在修改后的代码中这样做的第一次更新。
最后,还有一个问题。正如我之前对 1000 所说的,再次有一个例外。发生这种情况是因为长度计数错误。
int len = 1;
while (Math.pow((double)10, (double)len ) < num) {
len++;
}
对于 1000,它将返回 len = 3,但对于 1001,它将返回 len = 4。对于 10000,它将返回 len = 4,但对于 10001,它将返回 len = 5。
如果您有具体问题,请询问:)