最近看到了做J2ME开发的朋友们有人询问如何在MIDP1.0环境下进行开平方运算。正好自己对这个问题有一个比较好的解决办法,所以在这里和大家分享一下。
其实办法也比较简单,运算的过程对资源的占用也很少。具体的方法如下:
/**
* 得到算术平方根。
* @param num String 要开平方的数的字符串形式
* @param baoliu int 平方根中保留的小数的位数
* @return int[] 返回值,int[0]是平方根的整数部分,int[1]是平方根的小数部分
*/
public static int[] sqrt(String num, int baoliu) {
int index4Dot = num.indexOf(".");
int zheng = 0, xiao = 0, leftZeroNum = 0;
if (index4Dot >= 0) {
String zhengStr = num.substring(0, index4Dot); //整数部分
String xiaoStr = num.substring(index4Dot + 1, num.length()); //小数部分
zheng = Integer.parseInt(zhengStr);
xiao = Integer.parseInt(xiaoStr);
while ("0".equals(num.substring(index4Dot + 1 + leftZeroNum,
index4Dot + 2 + leftZeroNum))) {
leftZeroNum++;
}
} else {
zheng = Integer.parseInt(num);
}
if (baoliu > (19 - getAmount(zheng)) / 2) {
baoliu = (19 - getAmount(zheng)) / 2;
}
long square = decimalMoveLeft(zheng, baoliu * 2);
square += getLeft(xiao, baoliu * 2 - leftZeroNum);
int amount = getAmount(square);
int count = 1, beijianshu, yushu, shang;
int flag = amount % 2 == 0 ? 2 : 1;
int total = amount % 2 == 0 ? amount / 2 : amount / 2 + 1;
beijianshu = (int) getLeft(square, flag);
shang = getMaxPowerRoot(beijianshu);
yushu = beijianshu - shang * shang;
while (count < total) {
beijianshu = yushu * 100 + (int) (getLeft(square,
count * 2 + flag) % 100);
shang = getMaxShang(beijianshu, shang);
yushu = beijianshu - (shang / 10 * 20 + shang % 10) * (shang % 10);
count++;
}
int[] result = new int[2];
result[0] = (int) (shang / decimalMoveLeft(1, baoliu));
result[1] = (int) (shang % decimalMoveLeft(1, baoliu));
return result;
}
/**
* 得到最大商数
* @param yushu int
* @param shang int
* @return int
*/
public static int getMaxShang(int yushu, int shang) {
int num = 1;
while (yushu >= (shang * 20 + num) * num) {
num++;
}
return shang * 10 + num - 1;
}
/**
* 得到num(仅限两位数以内)的平方根。例如:“88”得到“9”;“3”得到“1”
* @param num int
* @return int
*/
public static int getMaxPowerRoot(int num) {
if (num < 4) {
return 1;
}
int root = 2;
while (num >= root * root) {
root++;
}
return root - 1;
}
/**
* 取得 num 左边的 wei 位数字。例如(12345,2)返回“12”;(12345,8)返回“12345000”
* @param num long 要运算的数字
* @param wei int 位数
* @return long
*/
public static long getLeft(long num, int wei) {
int amount = getAmount(num);
if (amount > wei) {
return decimalMoveRight(num, amount - wei);
} else if (amount < wei) {
return decimalMoveLeft(num, wei - amount);
} else {
return num;
}
}
/**
* 取得 num 的位数。例如:“0”是0位,“2”是1位,“12523”是5位
* @param num long 要统计位数的数字
* @return int
*/
public static int getAmount(long num) {
int count = 0;
if (num > 0) {
count++;
} while (num > 10) {
num /= 10;
count++;
}
return count;
}
/**
* 十进制左移
* @param num long 要左移的数
* @param left int 左移的位数
* @return long
*/
public static long decimalMoveLeft(long num, int left) {
while (left > 0) {
num *= 10;
left--;
}
return num;
}
/**
* 十进制右移
* @param num long 要右移的数
* @param right int 右移的位数
* @return long
*/
public static long decimalMoveRight(long num, int right) {
while (right > 0) {
num /= 10;
right--;
}
return num;
}
使用一个MIDlet调用测试一下:
protected void startApp() throws MIDletStateChangeException {
int[] root = new int[2];
root = sqrt("3", 7);
System.out.println("3 保留7位:/t" + root[0] + "." + root[1]);
root = sqrt("19", 7);
System.out.println("19 保留7位:/t" + root[0] + "." + root[1]);
root = sqrt("10.987", 7);
System.out.println("10.987 保留7位:/t" + root[0] + "." + root[1]);
root = sqrt("1000", 7);
System.out.println("1000 保留7位:/t" + root[0] + "." + root[1]);
root = sqrt("89798768.0987878", 7);
System.out.println("89798768.0987878 保留7位:/t" + root[0] + "." + root[1]);
}
输出如下:
3 保留7位: 1.7320508
19 保留7位: 4.3588989
10.987 保留7位: 3.3146643
1000 保留7位: 31.6227760
89798768.0987878 保留7位: 9476.22110
该方法占用CPU的时间很少,其中对字符串的解析占用了大部分的时间使用下面的方法代替一下,就会发现,CPU时间只是原来的1/3左右,呵呵。
/**
* 得到算术平方根。
* @param zheng int 要开方的数的整数部分
* @param xiao int 要开方的数的小数部分
* @param leftZeroNum int 小数部分左边的“0”的个数。例如“34.00932”中的小数点后面的两个“0”
* @param baoliu int 平方根中保留的小数的位数
* @return int[] 返回值,int[0]是平方根的整数部分,int[1]是平方根的小数部分
*/
public static int[] sqrt(int zheng, int xiao, int leftZeroNum, int baoliu) {
int[] result = new int[2];
if (baoliu > (19 - getAmount(zheng)) / 2) {
baoliu = (19 - getAmount(zheng)) / 2;
}
long square = decimalMoveLeft(zheng, baoliu * 2);
square += getLeft(xiao, baoliu * 2 - leftZeroNum);
int amount = getAmount(square);
int count = 1, beijianshu, yushu, shang;
int flag = amount % 2 == 0 ? 2 : 1;
int total = amount % 2 == 0 ? amount / 2 : amount / 2 + 1;
beijianshu = (int) getLeft(square, flag);
shang = getMaxPowerRoot(beijianshu);
yushu = beijianshu - shang * shang;
while (count < total) {
beijianshu = yushu * 100 + (int) (getLeft(square,
count * 2 + flag) % 100);
shang = getMaxShang(beijianshu, shang);
yushu = beijianshu - (shang / 10 * 20 + shang % 10) * (shang % 10);
count++;
}
result[0] = (int) (shang / decimalMoveLeft(1, baoliu));
result[1] = (int) (shang % decimalMoveLeft(1, baoliu));
return result;
}
对于这个方法,大家可以讨论一下。我的MSN:cuilichen@hotmail.com