www.pudn.com > 货币交换.rar > Converter.java~3~


/*
*
* Copyright 2004 FlashMan.Ncuhome.com Inc. All Rights Reserved.
*
* 我的第一个J2ME程序习作
* 用于在支持J2ME以及MIDP1.0的手机上进行不同货币单位的汇率换算(PS:其实是用于友人的作业)
* 本程序共有3个类,其中2个功能类
* Math类用来处理浮点数的四则运算
* MyInput类生成输入框,为的是更方便的输入数值.
*
* 本例中我有两个问题
* 1.List组件的setSelectedIndex(int elementNum,boolean selected)方法为何不能将
* 光标定位在指定的列上
* 2.在这个程序中我自定义了一个输入框类,能不能用不太麻烦的方法使它能像系统自带
* 的输入框一样支持光标显示
*
* 而且还有好些不足之处
* 1.用户不可以自已添加/删除货币单位及汇率,仅能通过联网更新
* 2.从菜单中选择Restore Rate时不经用户确认就将数据库复位
* 3.代码不够优化(比如:用了太多的Command对象引用)
*
* 还有一点需要提醒一下的是通过联网更新汇率的方法只在Jbuilder9自带的J2ME Wireless Toolkit 1.0
* 能正常连网,如果是J2ME Wireless Toolkit 2.1的SDK就会发现点enter准备更新的时候它会"善意"的告诉
* 程序想要访问网络,这将会产生某些费用,然后给你两个选择Yes/No.再然后你就会发现它已经死掉了,不论
* 你选择的是YesOrNo.
*
* 有任何建议和意见请发邮件至itfeihu@163.com
* 也可通过我的早期作品闪狐超酷Flash留言板给我留言 flashbook.ncuhome.com
* 同时欢迎访问我的个人主页 flashman.ncuhome.com
* 当然也欢迎访问我们的校园网站"南昌大学家园网"
*/


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import javax.microedition.io.*;
import java.io.*;

public class Converter
extends MIDlet
implements CommandListener {

String dbName = "Converter"; //数据库名

String CurrencyName[]; //用于存放货币单位的数组
String Rate[][]; //用于存放货币之间的交叉汇率

String money_s = "0"; //源货币
String money_t = "0"; //目标货币
int source = 0; //源货币单位在数组中的位置
int object = 0; //目标货币单位在数组中的位置
int selected = 0; //当前选择的菜单项位置
String updateURL; //提供更新汇率的网址

Alert alert = new Alert("Alert"); //定义一个用于提示信息的Alert
Display display; //定义屏幕对象
MyInput myInput; //定义一个输入框
Math math = new Math(); //浮点运算类

public Converter() {
alert.setType(AlertType.WARNING); //设置alert的类型
alert.setTimeout(3000); //alert的显示时间
display = Display.getDisplay(this); //获得对屏幕控制的引用
}

public void startApp() {
openDb(); //从数据库中获取汇率和恢复上一次正常退出时的状态
main(); //运行界面
renewVar(); //更新所有的变量状态
}

public void pauseApp() {}

public void destroyApp(boolean unconditional) {}

List list; //定义一个List组件用于显示选单
Command cmdExit; //定义一个Command按纽组件
void main() {

cmdExit = new Command("Exit", Command.EXIT, 0); //生成Command对象(显示内容,按纽型态,显示优先级)
list = new List("Rate Converter", Choice.IMPLICIT); //生成List(主选单)(标题,型态[单选])

//追加各个选单
list.append("From " + CurrencyName[source], null);
list.append("To " + CurrencyName[object], null);
list.append("Rate 1:" + Rate[source][object], null);
list.append("Valuta:" + money_s, null);
list.append("Result:" + money_t, null);

//追回系统选单
list.addCommand(cmdExit);
list.addCommand(new Command("Update rate", Command.SCREEN, 0));
list.addCommand(new Command("Restore rate", Command.SCREEN, 0));
list.addCommand(new Command("About", Command.SCREEN, 0));

list.setCommandListener(this); //设置事件监听

list.setSelectedIndex(selected, true);
//设置光标定位在上次操作选定的选单
//但不知为何就是不行,明明是说设成true的,这是我的问题之一

display.setCurrent(list); //显示选单

}

//选择源货币单位
List sourceList;
Command sourceEnter;
Command sourceCancel;
void SelectSource() {

sourceList = new List("Choose Source", Choice.EXCLUSIVE);
sourceEnter = new Command("Enter", Command.OK, 0);
sourceCancel = new Command("Cancel", Command.CANCEL, 1);

for (int I = 0; I < CurrencyName.length; I++) { //将货币单位全部添至选单
sourceList.append(CurrencyName[I], null); //null这个位置的参数可以用来显示图像
}

//添加按纽及设置事件监听
sourceList.addCommand(sourceEnter);
sourceList.addCommand(sourceCancel);
sourceList.setCommandListener(this);

sourceList.setSelectedIndex(source, true);
//设置光标定位在上次操作选定的选单,但和前面一样无效
display.setCurrent(sourceList);

}

//选择目标货币单位
List objectList;
Command objectEnter;
Command objectCancel;
void SelectObject() {

//同上
objectList = new List("Choose Object", Choice.EXCLUSIVE);
objectEnter = new Command("Enter", Command.OK, 0);
objectCancel = new Command("Cancel", Command.CANCEL, 1);

for (int I = 0; I < CurrencyName.length; I++) {
objectList.append(CurrencyName[I], null);
}

objectList.addCommand(objectEnter);
objectList.addCommand(objectCancel);
objectList.setCommandListener(this);

objectList.setSelectedIndex(object, true);
//设置光标定位在上次操作选定的选单,照样无效
display.setCurrent(objectList);

}

Command setRateEnter;
Command setRateCancel;
void setRate() { //修改汇率

myInput = new MyInput(34, 53, Rate[source][object]); //在x:34,y:53的位置显示输入框,并传递原汇率值
setRateEnter = new Command("Enter", Command.OK, 0);
myInput.addCommand(setRateEnter);

setRateCancel = new Command("Cancel", Command.CANCEL, 1);
myInput.addCommand(setRateCancel);

display.setCurrent(myInput);
myInput.setCommandListener(this);

}

Command inputEnter;
Command inputCancel;
void inputMoney() { //输入货币金额

myInput = new MyInput(34, 69); //指定位置显示一个空白的输入框
inputEnter = new Command("Enter", Command.OK, 0);
myInput.addCommand(inputEnter);

inputCancel = new Command("Cancel", Command.CANCEL, 1);
myInput.addCommand(inputCancel);

display.setCurrent(myInput);
myInput.setCommandListener(this);

}

Command reverseEnter;
Command reverseCancel;
void reverseMoney() { //反向金额输入

myInput = new MyInput(33, 85); //指定位置显示一个空白的输入框
reverseEnter = new Command("Enter", Command.OK, 0);
myInput.addCommand(reverseEnter);

reverseCancel = new Command("Cancel", Command.CANCEL, 1);
myInput.addCommand(reverseCancel);

display.setCurrent(myInput);
myInput.setCommandListener(this);

}

TextField input;
Command updateEnter;
Command updateCancel;
void updateRate() { //连网更新数据

Form form = new Form("Update rate");

updateEnter = new Command("Enter", Command.OK, 0);
form.addCommand(updateEnter);

updateCancel = new Command("Cancel", Command.CANCEL, 0);
form.addCommand(updateCancel);

input = new TextField("Update's URL:", updateURL, 100, TextField.URL);
form.append(input);

form.setCommandListener(this);
display.setCurrent(form);

}

public void commandAction(Command c, Displayable s) { //用于响应所有的操作事件

if (c.getLabel() == "Restore rate") { //初始化数据库
dbInitialize();
startApp();
return;
}

if (c.getLabel() == "Update rate") { //汇率更新界面
updateRate();
return;
}

if (c.getLabel() == "About") { //汇率更新界面
alert.setString("Copyright(c)2004 FlashMan.Ncuhome.Com"); //提示无效的URL链接或无效的数据页
alert.setTimeout(6000);
display.setCurrent(alert);
alert.setTimeout(3000);
return;
}

if (c == updateEnter) { //汇率主更新程序(汇率更新界面)
StartUpdate();
return;
}

if (c == updateCancel) { //取消更新(汇率更新界面)
main();
return;
}

if (c == sourceEnter) { //源货币单位选择
source = sourceList.getSelectedIndex();
money_t = math.Multiplication(money_s, Rate[source][object]); //计算货币单位变更后的转换结果
main();
return;
}

if (c == sourceCancel) { //取消选择源货币(源货币单位选择界面)
main();
return;
}

if (c == objectEnter) { //目标币单位选择
object = objectList.getSelectedIndex();
money_t = math.Multiplication(money_s, Rate[source][object]); //计算货币单位变更后的转换结果
main();
return;
}

if (c == objectCancel) { //取消选择目标货币(源货币单位选择界面)
main();
return;
}

if (c == cmdExit) { //正常退出
saveDb(); //将各变量状态保存至数据库
notifyDestroyed();
return;
}

if (c == inputEnter) { //转换值输入
money_s = myInput.value.toString(); //myInput是自定义的输入框类
if (money_s.length() < 1) {
money_s = "0";
}
money_t = math.Multiplication(money_s, Rate[source][object]); //计算转换结果
main();
return;
}

if (c == inputCancel) { //取消输入(转换值)
main();
return;
}

if (c == reverseEnter) { //在结果中输入(反向转换)
money_t = myInput.value.toString();
if (money_s.length() < 1) {
money_s = "0";
}
money_s = math.Division(money_t, Rate[source][object]); //计算转换结果
main();
return;
}

if (c == reverseCancel) { //取消输入(反向转换)
main();
return;
}

if (c == setRateEnter) { //设定已选定的源/目标货币之间的汇率

if (CurrencyName[source] != CurrencyName[object]) {
; //如果源货币等于目标货币则不更新汇率(得保持为1:1)
Rate[source][object] = myInput.value.toString(); //更新汇率
Rate[object][source] = math.Division("1", Rate[source][object]); //反向更新汇率
money_t = math.Multiplication(money_s, Rate[source][object]); //更新结果
}
main();
return;
}

if (c == setRateCancel) { //取消汇率设定
main();
return;
}

switch (list.getSelectedIndex()) { //根据选定的选单进行相应的操作
case 0:
selected = 0;
SelectSource(); //选择源货币单位
break;
case 1:
selected = 1;
SelectObject(); //选择目标货币单位
break;
case 2:
selected = 2;
setRate(); //设定汇率
break;
case 3:
selected = 3;
inputMoney(); //输入转换值
break;
case 4:
selected = 4;
reverseMoney(); //反向转换输入值
break;
}

}

void openDb() { //从数据库中获取汇率和恢复上一次正常退出时的状态

try {
RecordStore rs = RecordStore.openRecordStore(dbName, false);
/*
定义数据库的引用对象
第二个参数如果是true代表如果指定的数据库不存在,则系统将自动建立一个新的数据库
反之则抛出RecordStoreNotFoundException异常
*/

byte bytes[];
String str;

bytes = rs.getRecord(1); //取出第一行记录,本程序将其设置的是货币单位
str = new String(bytes, 0, bytes.length); //将取出的bytes型数据转成字符型
str = str.trim(); //剔除空行
CurrencyName = newArray(str, ","); //更新一维数组变量CurrencyName

bytes = rs.getRecord(2); //同上,汇率
str = new String(bytes, 0, bytes.length);
str = str.trim();
Rate = newArrayPlanar(str, "|", ","); //更新二维数组变量Rate

bytes = rs.getRecord(3); //同上,程序状态
str = new String(bytes, 0, bytes.length);
str = str.trim();
/*更新最后一次正常退出时的程序状态,如:
str="50,413.5,1,2,0,http://localhost/rate.asp"
需用newArray将其转换成数组
*/
String tmpArray[] = newArray(str, ",");
money_s = tmpArray[0];
money_t = tmpArray[1];
source = Integer.parseInt(tmpArray[2]);
object = Integer.parseInt(tmpArray[3]);
selected = Integer.parseInt(tmpArray[4]);
updateURL = tmpArray[5];

rs.closeRecordStore(); //关闭数据库对象

}
catch (RecordStoreException ex) { //捕捉到错误异常(第一次运行的时候数据库不存在)
dbInitialize(); //初始化数据库
startApp(); //重新开始程序
}

}

void saveDb() { //保存程序运行状态

renewVar(); //更新变量

try {
RecordStore rs = RecordStore.openRecordStore(dbName, true);

byte bytes[];

//字符串得转成Byte型再写入数据库
bytes = newArrayByte(defCurrencyName);
rs.setRecord(1, bytes, 0, bytes.length);
bytes = newArrayByte(defRate);
rs.setRecord(2, bytes, 0, bytes.length);
bytes = newArrayByte(defOperation);
rs.setRecord(3, bytes, 0, bytes.length);

rs.closeRecordStore();

// System.out.println("Database " + dbName + "Save Seucceed!");

}
catch (RecordStoreException e) {
}
}

//用于初始状态值
String defCurrencyName;
String defRate;
String defOperation;

void dbInitialize() { //初始化数据库

//初始状态值
defCurrencyName = "Pound,Dollar,RMB,ECU";
defRate = "1,1.81,15.02,1.497"
+ "|0.55,1,8.27,0.825"
+ "|0.067,0.12,1,0.1"
+ "|0.668,1.21,10.035,1";
defOperation = "0,0,0,0,0,http://localhost/rate.asp";

try {
RecordStore.deleteRecordStore(dbName); //管它有没有数据库,删了再说
}
catch (RecordStoreException ex) {
}

try {
//删了再建一个新的,现在这里的参数用了true,也就是数据库不存在的话系统就会帮你建一个.
RecordStore rs = RecordStore.openRecordStore(dbName, true);

byte bytes[];

//将初始数据存进数据库
bytes = newArrayByte(defCurrencyName);
rs.addRecord(bytes, 0, bytes.length);
bytes = newArrayByte(defRate);
rs.addRecord(bytes, 0, bytes.length);
bytes = newArrayByte(defOperation);
rs.addRecord(bytes, 0, bytes.length);

rs.closeRecordStore();

// System.out.println("Database " + dbName + "Initialize Seucceed!");

}
catch (RecordStoreException ex) {
}

}

void renewVar() { //更新变量信息

defCurrencyName = "";
defRate = "";
defOperation = "";

for (int I = 0; I < CurrencyName.length; I++) { //更新货币单位
defCurrencyName += CurrencyName[I];
if (I < CurrencyName.length - 1) {
defCurrencyName += ",";
}
}

for (int I = 0; I < Rate.length; I++) { //更新汇率
for (int J = 0; J < Rate[I].length; J++) {
defRate += Rate[I][J];
if (J < Rate[I].length - 1) {
defRate += ",";
}
}
if (I < Rate.length - 1) {
defRate += "|";
}
}

//更新状态
defOperation += money_s + ",";
defOperation += money_t + ",";
defOperation += source + ",";
defOperation += object + ",";
defOperation += selected + ",";
defOperation += updateURL;

}

void StartUpdate() { //联网更新汇率

try {
//从指定网址读取汇率值
updateURL = input.getString();
HttpConnection hc = (HttpConnection) Connector.open(updateURL); //生成连接对像
DataInputStream dis = new DataInputStream(hc.openInputStream()); //获取输入流

String content = "";
int ic;
while ( (ic = dis.read()) != -1) { //读取一行
if (ic == 13) {
dis.read();
break;
}
content += (char) ic; //累加读取的字符
}
if (content.compareTo("RateData") == 0) { //如果第一行不是RateData则该页面不是有效的汇率数据

content = "";
while ( (ic = dis.read()) != -1) {
if (ic == 13) {
dis.read();
break;
}
content += (char) ic;
}
CurrencyName = newArray(content, ","); //更新货币单位

content = "";
while ( (ic = dis.read()) != -1) {
if (ic == 13) {
dis.read();
break;
}
content += (char) ic;
}
Rate = newArrayPlanar(content, "|", ","); //更新汇率

alert.setString("Update rate succeed!"); //提示更新成功
display.setCurrent(alert);

}
else {
alert.setString("Invalid URL or files!"); //提示无效的URL链接或无效的数据页
display.setCurrent(alert);
}

}
catch (Exception e) {
alert.setString("Connecting field!"); //提示联接失败
display.setCurrent(alert);
}

}

static String[] newArray(String Str, String sign) {
/*
以分隔符划分生成一维数组
其实就等于split函数,我当时翻的一本书叫<<Java2应用开发指南>>,里面介绍的String类
竟然找不到split这个函数,结果导致我错误的认为"Java居然不提供split",然后就傻傻
的自己写了一个同样功能的函数
这个错误还是今天整理这个程序的时候想起来查了一下SDK才发现的
不过还好这个功能并不复杂,自己写了也没花什么功夫,不过J2ME不支持浮点运算,这可写
死我了.
*/

int point = 1;
int incept = 0;
int count = 0;

while (point > 0) {
point = Str.indexOf(sign, point);
point += 1;
incept = point;
count += 1;
}
String tmpArray[] = new String[count]; //确定数组大小

//复位初始位置
point = 1;
incept = 0;
int I = 0;
while (point > 0) {

point = Str.indexOf(sign, point);
point += 1;

if (point != 0) { //数组元素赋值
tmpArray[I] = Str.substring(incept, point - 1);
}
else {
tmpArray[I] = Str.substring(incept);
}

I++;
incept = point;
}

return tmpArray;
}

static String[][] newArrayPlanar(String Str, String firstSign,
String secondSign) {
//以分隔符划分生成二维数组
//这个Java好像没有吧,这回没白写

String firstArray[] = newArray(Str, firstSign);
String secondArray[] = newArray(firstArray[0], secondSign);
String tmpArray[][] = new String[firstArray.length][secondArray.length]; //确定数组大小

for (int I = 0; I < firstArray.length; I++) {
secondArray = newArray(firstArray[I], secondSign);
for (int J = 0; J < secondArray.length; J++) {
tmpArray[I][J] = secondArray[J]; //数组元素赋值
}
}

return tmpArray;
}

static String[] newArrayLength(String original[], int length) {
//用于动态改变数组大小
//如果增加一个功能,用户可以自己添加删除货币单位,就要用到
String tmpArray[] = new String[length];
System.arraycopy(original, 0, tmpArray, 0, original.length);
return tmpArray;
}

static byte[] newArrayByte(String string) { //字符串转Byte数组
byte tmpArray[] = string.getBytes();
return tmpArray;
}

}

class MyInput
extends Canvas { //自定义输入框的类
/*
系统自带组件TextField不能很好的处理小数点输入问题
大多数情况输入小数点需要切换到字符模式下
这样用户输入带小数点的数值会很不方便
所有需要自已定义一个这样的输入框类
*/

public StringBuffer value = new StringBuffer(""); //存放输入的字符
int maxLength = 10; //最大输入字符数
int X, Y; //输入框的坐标

public MyInput(int x, int y) { //构造方法1
X = x;
Y = y;
}

public MyInput(int x, int y, String str) { //构造方法2
X = x;
Y = y;
input(str); //赋初值
}

public void paint(Graphics screen) {
screen.setColor(255, 255, 255); //设置前景色为白色
screen.fillRect(X, Y, getWidth() - 38, 12); //用白色填充指定区域
screen.setColor(0, 0, 0); //恢复前景色为黑色
screen.drawString(value.toString(), X + 2, Y - 2, 0); //将输入的字符串输出到指定位置
}

void input(String str) {
if (value.length() < maxLength) { //不超过最大字符数
value.append(str); //添加输入的字符
}
}

protected void keyReleased(int key) {

switch (key) { //输入按键输入

case 48:
input("0");
break;
case 49:
input("1");
break;
case 50:
input("2");
break;
case 51:
input("3");
break;
case 52:
input("4");
break;
case 53:
input("5");
break;
case 54:
input("6");
break;
case 55:
input("7");
break;
case 56:
input("8");
break;
case 57:
input("9");
break;

case 35: //处理负号输入
if (value.toString().indexOf("-") < 0) {
value.insert(0, "-");
}
else {
value.delete(0, 1);
}
break;

case 42: //处理小数点输入
if (value.toString().indexOf(".") < 0 &amt;&amt; value.length() > 0) {
if ( (value.toString().indexOf("-") < 0 &amt;&amt; value.length() >= 1) ||
(value.toString().indexOf("-") == 0 &amt;&amt; value.length() >= 2)) {
input(".");
}
}
break;

case -8: //退格清除
if (value.length() > 0) {
value.delete(value.length() - 1, value.length());
}
break;

}
repaint();
}

}

class Math {

//+-*/这4个方法让我好是研究了一阵子,但我还是觉得方法笨了点
//这个程序只用到了*/法

public static String Add(String X, String Y) {

//浮点数加法运算
//处理步骤:
// 1.将浮点数的整数部分和小数部分分离出来
// 2.让小数位同位
// 3.整数部分运算
// 4.小数部分运算
// 5.处理小数位进位
// 6.返回运算结果。

long Xi, Xf; //X的整数部分Xi,X的小数部分Xf
long Yi, Yf; //X的整数部分Yi,X的小数部分Yf
long Ri, Rf; //Ri存放整数部分的运算结果,Rf存放小数部分的运算结果
int Xp, Yp; //Xp,Yp用于处理小数位长度
String a, b; //两个临时变量,用于处理小数位运算后进位,a为运算后的进位部分,b为运算后的小数部分

String tmp; //临时变量

Xi = Long.parseLong(getInt(X)); //X的整数部分
Xf = Long.parseLong(getFloat(X)); //X的小数部分
Xp = getFloat(X).length(); //X小数部分的位数

Yi = Long.parseLong(getInt(Y)); //Y的整数部分
Yf = Long.parseLong(getFloat(Y)); //Y的小数部分
Yp = getFloat(Y).length(); //Y小数部分的位数

//处理同位运算
tmp = "1";
if (Xp > Yp) { //例:X=10.232 Y=12.8

for (int I = 0; I < (Xp - Yp); I++) {
tmp += "0";
//生成进位值 如上例 X有3位小数,Y有1位小数,3-1=2 循环2次生成进位值"1"+"0"+"0" ="100"
}

Yf = Yf * Long.parseLong(tmp); //如上例 Y的小数8*进位值100=800 这样小数位的运算就变成了232和800
Yp = Xp; //同步小数位
}

if (Xp < Yp) { //例:X=10.2 Y=12.83

for (int I = 0; I < (Yp - Xp); I++) {
tmp += "0";
//生成进位值 如上例 X有1位小数,Y有2位小数,2-1=1 循环1次生成进位值"1"+"0" ="10"
}

Xf = Xf * Long.parseLong(tmp); //如上例 X的小数2*进位值10=20 这样小数位的运算就变成了20和83
Xp = Yp; //同步小数位
}

Ri = Xi + Yi; //X、Y整数部分相加
Rf = Xf + Yf; //X、Y小数部分相加

tmp = String.valueOf(Rf); //获取分开运算后的小数值

if (tmp.length() < Xp) { //位数不够前面补"0"
for (int I = tmp.length(); I < Xp; I++) {
tmp = "0" + tmp;
}
return FormatFloat(Ri + "." + tmp, 2); //返回运算结果
}

if (tmp.length() > Xp) { //运算后小数位长度大于原长度要处理进位问题

a = tmp.substring(0, 1); //提取进位数
b = tmp.substring(1, Xp + 1); //提取小数部分

Ri += Byte.parseByte(a); //将原X、Y整数部分运算后的结果加上刚提取出来的进位数

return FormatFloat(Ri + "." + b, 2); //返回运算结果

}
else {
return FormatFloat(Ri + "." + Rf, 2); //直接返回运算结果
}

}

public static String Subtract(String X, String Y) {

//浮点数减法运算
//处理步骤:
// 1.将浮点数的整数部分和小数部分分离出来
// 2.让小数位同位
// 3.整数部分运算
// 4.处理小数位借位
// 5.小数部分运算
// 6.返回运算结果。

long Xi, Xf; //X的整数部分Xi,X的小数部分Xf
long Yi, Yf; //X的整数部分Yi,X的小数部分Yf
long Ri, Rf; //Ri存放整数部分的运算结果,Rf存放小数部分的运算结果
int Xp, Yp; //Xp,Yp用于处理小数位长度
String Sign = ""; //用算负数标志
String tmp; //用于小数位同位计算

if (XbigmoreY(X, Y) == 0) { //如果X小于Y则对它们进行数值互换
tmp = X;
X = Y;
Y = tmp;
Sign = "-"; //并且添加负数标志
}

Xi = Long.parseLong(getInt(X)); //提取X的整数部分
Xf = Long.parseLong(getFloat(X)); //提取X的小数部分
Xp = getFloat(X).length(); //获取X小数部分的位数

Yi = Long.parseLong(getInt(Y)); //提取Y的整数部分
Yf = Long.parseLong(getFloat(Y)); //提取Y的小数部分
Yp = getFloat(Y).length(); //获取Y小数部分的位数

//处理同位运算
tmp = "1";
if (Xp > Yp) { //例:X=10.232 Y=12.8

for (int I = 0; I < (Xp - Yp); I++) {
tmp += "0";
//生成进位值 如上例 X有3位小数,Y有1位小数,3-1=2 循环2次生成进位值"1"+"0"+"0" ="100"
}

Yf = Yf * Long.parseLong(tmp); //如上例 Y的小数8*进位值100=800 这样小数位的运算就变成了232和800
Yp = Xp; //同步小数位
}

if (Xp < Yp) { //例:X=10.2 Y=12.83

for (int I = 0; I < (Yp - Xp); I++) {
tmp += "0";
//生成进位值 如上例 X有1位小数,Y有2位小数,2-1=1 循环1次生成进位值"1"+"0" ="10"
}

Xf = Xf * Long.parseLong(tmp); //如上例 X的小数2*进位值10=20 这样小数位的运算就变成了20和83
Xp = Yp; //同步小数位
}

Ri = Xi - Yi; //X、Y整数部分相减

if (Xf < Yf) { //如果X的小数部分比Y的小数部分小则Xf借位
tmp = "1";
for (int I = 1; I < Xp; I++) {
tmp += "0";
}
Xf += Long.parseLong(tmp += "0"); //加上进位值
Ri -= 1; //整数部分相应减1
}

Rf = Xf - Yf; //X、Y小数部分相减

tmp = String.valueOf(Rf);
for (int I = tmp.length(); I < Xp; I++) { //如果长度不够在前面补足"0"
tmp = "0" + tmp;
}

return Sign + FormatFloat(Ri + "." + tmp, 2); //返回运算结果

}

public static String Multiplication(String X, String Y) {

//浮点数乘法运算
//处理步骤:
// 1.获取小数点位数
// 2.将浮点数进位成整数
// 3.进位后的整数运算
// 4.处理小数位数
// 5.返回运算结果

int Xp, Yp; //Xp,Yp用于处理小数位长度
String tmp, a, b; //临时存贮用变量

a = getFloat(X); //X的小数部分
b = getFloat(Y); //Y的小数部分

if (Long.parseLong(a) == 0) {
a = "";
}
if (Long.parseLong(b) == 0) {
b = "";

}
Xp = a.length(); //获取X小数部分的位数
Yp = b.length(); //获取Y小数部分的位数

X = getInt(X) + a; //进位成整数
Y = getInt(Y) + b; //进位成整数

tmp = String.valueOf( (Long.parseLong(X) * Long.parseLong(Y))); //进位后的运算结果

for (int I = tmp.length(); I < (Xp + Yp); I++) { //如果长度不够在前面补足"0"
tmp = "0" + tmp;
}

a = tmp.substring(0, tmp.length() - (Xp + Yp)); //结果整数部分
b = tmp.substring(tmp.length() - (Xp + Yp), tmp.length()); //结果小数部分

if (a.length() == 0) {
a = "0"; //整数部分为空等于0

}
return FormatFloat(a + "." + b, 2); //返回运算结果

}

public static String Division(String X, String Y) {

//浮点数除法运算
//处理步骤:
// 1.获取小数点位数
// 2.将浮点数进位成整数
// 3.直除取得商值(整数部分)
// 4.反复进行商、余运算直到除尽或达到最大精确位(小数部分)
// 5.返回运算结果

long Xf, Yf; //Xi存放X的小数部分,Xf存放Y的小数部分
long Xt, Yt; //临时绝对值后的X和Y
long Quotient, Remainder, Result; //Quotient商、Remainder余、结果Result
int Xp, Yp; //Xp,Yp用于处理小数位长度
String tmp, a, b; //临时存贮用变量

a = getFloat(X); //X的小数部分
b = getFloat(Y); //Y的小数部分

if (Long.parseLong(a) == 0) {
a = "";
}
if (Long.parseLong(b) == 0) {
b = "";

}
Xp = a.length(); //获取X小数部分的位数
Yp = b.length(); //获取Y小数部分的位数

X = getInt(X) + a; //进位成整数
Y = getInt(Y) + b; //进位成整数

//处理同位运算
tmp = "1";
if (Xp > Yp) { //例:X=10.232 Y=12.8

for (int I = 0; I < (Xp - Yp); I++) {
tmp += "0";
//生成进位值 如上例 X有3位小数,Y有1位小数,3-1=2 循环2次生成进位值"1"+"0"+"0" ="100"
}

Y = "" + Long.parseLong(Y) * Long.parseLong(tmp); //如上例 Y的小数8*进位值100=800 运算就变成了10232和12800
Yp = Xp; //同步小数位

}

if (Xp < Yp) { //例:X=10.2 Y=12.83

for (int I = 0; I < (Yp - Xp); I++) {
tmp += "0";
//生成进位值 如上例 X有1位小数,Y有2位小数,2-1=1 循环1次生成进位值"1"+"0" ="10"
}

X = "" + Long.parseLong(X) * Long.parseLong(tmp); //如上例 X的小数2*进位值10=20 这样运算就变成了1020和1283
Xp = Yp; //同步小数位
}

Xt = Long.parseLong(X); //临时将X移到Xt上
Yt = Long.parseLong(Y); //临时将Y移到Yt上
if (Xt < 0) {
Xt *= -1; //保证Xt为正数
}
if (Yt < 0) {
Yt *= -1; //保证Yt为正数

}
tmp = "";
Remainder = Xt;

for (int I = 0; I < 16; I++) { //反复进行商、余运算直到除尽或达到最大精确位
Quotient = Remainder / Yt; //求商
Remainder = Remainder - (Quotient * Yt); //求余
if (Remainder == 0) {
break; //如果余等于0表示除尽则跳出运算
}
Remainder *= 10; //进位
Result = Remainder / Yt; //单次运算结果
tmp += Result; //累加结果
}

if (tmp == "") {
tmp = "0";

}
return FormatFloat(Long.parseLong(X) / Long.parseLong(Y) + "." + tmp, 2); //返回运算结果

}

static String getInt(String I) { //提取浮点数整数部分

int point; //point变量存贮小数点在浮点数中的位置
point = I.indexOf("."); //捕捉小数点位置

if (point == 0) {
return "0"; //"."在第1位直接返回0
}

if (point < 0) { //(找不到"."point值为-1)
return I; //如果没有小数点则直接返回整数
}
else {
return I.substring(0, point); //找到就返回小数点前段部分
}

}

static String getFloat(String I) { //提取浮点数小数部分

int point; //point变量存贮小数点在浮点数中的位置
point = I.indexOf("."); //捕捉小数点位置

if (point < 0 || point == (I.length() - 1)) {
return "0"; //找不到"."或"."在最后1位直接返回0
}
else {
point += 1; //在"."位置上向后移一位是为了方便将小数部分提取出来
return I.substring(point, I.length()); //找到就返回小数点后段部分
}

}

static int XbigmoreY(String X, String Y) { //浮点数比较X是否大于Y

long Xi, Xf; //X的整数部分Xi,X的小数部分Xf
long Yi, Yf; //Yi存放Y的整数部分,Yf存放Y的小数部分
int Xp, Yp; //Xp、Yp用于处理小数位长度
String tmp; //临时变量

Xi = Long.parseLong(getInt(X)); //提取X的整数部分
Xf = Long.parseLong(getFloat(X)); //提取X的小数部分
Xp = getFloat(X).length(); //获取X小数部分的位数

Yi = Long.parseLong(getInt(Y)); //提取Y的整数部分
Yf = Long.parseLong(getFloat(Y)); //提取Y的小数部分
Yp = getFloat(Y).length(); //获取Y小数部分的位数

//处理同位运算
tmp = "1";
if (Xp > Yp) { //例:X=10.232 Y=12.8

for (int I = 0; I < (Xp - Yp); I++) {
tmp += "0";
//生成进位值 如上例 X有3位小数,Y有1位小数,3-1=2 循环2次生成进位值"1"+"0"+"0" ="100"
}

Yf = Yf * Long.parseLong(tmp); //如上例 Y的小数8*进位值100=800 这样小数位的运算就变成了232和800
Yp = Xp; //同步小数位
}

if (Xp < Yp) { //例:X=10.2 Y=12.83

for (int I = 0; I < (Yp - Xp); I++) {
tmp += "0";
//生成进位值 如上例 X有1位小数,Y有2位小数,2-1=1 循环1次生成进位值"1"+"0" ="10"
}

Xf = Xf * Long.parseLong(tmp); //如上例 X的小数2*进位值10=20 这样小数位的运算就变成了20和83
Xp = Yp; //同步小数位
}

if ( (Xi == Yi) &amt;&amt; (Xf == Yf)) {
return 2; //如果X=Y返回2
}

if ( (Xi > Yi) || ( (Xi == Yi) &amt;&amt; (Xf > Yf))) {
return 1; //X大Y返回1
}
else {
return 0; //否则返回0
}
}

static String FormatFloat(String X, int length) { //用来处运算结果小数部分多余的0

String Xi, Xf, tmp; //整数部分Xi,小数部分Xf,临时变量tmp

Xi = getInt(X); //X的整数部分
Xf = getFloat(X); //X的小数部分

if (Xf.length() > length) {
Xf = Xf.substring(0, length);
}
int Xl = Xf.length(); //小数部分长度

for (int I = 1; I < Xl; I++) {
tmp = Xf.substring(Xf.length() - 1, Xf.length()); //提取最尾数

if (Byte.parseByte(tmp) == 0) {
Xf = Xf.substring(0, Xf.length() - 1); //如果最尾数是0就剔除
}
else {
break; //否则跳出
}
}

if (Long.parseLong(Xf) == 0) {
tmp = ""; //如果X的小数部分等于0就剔除小数点
}
else {
tmp = "." + Xf; //否则保持原样
}

return Xi + tmp; //返回处理结果
}

}