import com.google.common.base.Preconditions;
/**
* 打印大数:
*
* 1)字符和整数(0~127)之间可以相互转换,ascii码表中维护着字符和整数之间的映射关系。
* char emptyChar = 0; // emptyChar表示空字符
* char zeroChar = '0'; // zeroChar表示字符0
* int emptyCharIntValue = emptyChar; // 空字符转换为整数的值为0 即:emptyCharIntValue==0
* int zeroCharIntValue = zeroChar; // 字符0转换为整数的值为48 即:zeroCharIntValue==48
*
* 2)若n和m的取值为0~9之间的整数,则:
* 1> 'n' - 'm' == (n-'0') - (m-'0') == n - m
* 2> 'n' + 'm' == (n-'0') + (m-'0')
* 3> 将数字形式转换为字符形式: n + '0' == 'n'
*
* 3)故可以使用字符串(字符数组)来表示大数,用字符间的运算来实现对大数的运算。
*
*/
public class NumberAndChar {
/**
* 问题:输入整数n,按顺序打印出从1到最大的n位数。
*
* 注意:若n较大时,则最大的n位数是一个很大的数,这个大数无法用long类型表示。
*
* @param n
*/
public static void print1ToMaxOfNDigits(int n) {
Preconditions.checkArgument(n > 0);
StringBuffer numberStr = new StringBuffer();
for(int i = 0; i < n; i++){
numberStr.append('0');
}
while(!increment4NumberStr(numberStr)){
printNumberStr(numberStr);
}
}
/**
* 说明:
* 1)将numberStr代表的数字进行+1操作。
* 2)numberStr的初始值由numberStr.length个'0'字符组成。
* 3)该数字是numberStr.length位数字,若该数字+1后变成了numberStr.length+1位,则表示发生了溢出。
*
* @param numberStr
*
* @return +1后是否发生了溢出
*
*/
public static boolean increment4NumberStr(StringBuffer numberStr) {
boolean isOverflow = false; // +1后是否发生了溢出。
int carry = 0; // 前一位+1后产生的进位。
int length = numberStr.length(); // 数字的位数
/**
* 将最低位+1
* 若没有发生进位,则执行一次后就退出循环。
* 若发生了进位, 则需要执行两次循环,然后退出。
*/
for (int i = length - 1; i >= 0; i--) {
int nSum = (numberStr.charAt(i) - '0') + carry; // 获取该位上的值
if (i == length - 1) { // 将最低位+1
nSum++;
}
if (nSum < 10) { // 将最低位+1后没有产生进位。
numberStr.setCharAt(i, (char)('0' + nSum));
break;
} else { // 将最低位+1后产生了进位,所以还需要再次进入循环来计算高位的值。
if (i == 0) { // 在最高位+1后产生了进位,也就是说本次的+1操作导致了溢出。
isOverflow = true;
} else {
nSum -= 10; // 因为发生了进位,故该位应该减10
carry = 1; // 因为是+1导致的进位,故进位量为1
numberStr.setCharAt(i, (char) ('0' + nSum)); // 设置该位上的值
}
}
}
return isOverflow;
}
/**
* 打印表示数字的字符串:
*
* 注意:打印时,去掉开头的0
*
* @param numberStr
*/
public static void printNumberStr(StringBuffer numberStr) {
boolean beginFlag = false;
for (int i = 0; i < numberStr.length(); i++) {
if (!beginFlag && numberStr.charAt(i) != '0') {
beginFlag = true;
}
if (beginFlag) {
System.out.print(numberStr.charAt(i));
}
}
}
public static void main(String[] args) {
print1ToMaxOfNDigits(3);
}
}