封装MathFP和FloatBox

作者:黑洞

前几天看到mathfp的文章,很有些激动,
有了浮点数很多不能做的事情都变为可能。
但是一大堆MathFP开头的函数和不断的转换让人头大。
于是就想着自己封装一下,很多人都有这个想法吧:)
我的这个叫做Float。

1。首先是浮点常数,这个没什么好说的

public static final Float PI = new Float(MathFP.PI);
public static final Float E = new Float(MathFP.E);
public static final Float pi2 = PI.div(2);
public static final Float pi4 = PI.div(4);
public static final Float pi = PI.div(180); //PI/180
public static final Float neg1 = new Float( -1); //-1
public static final Float pos1 = new Float(1); //+1
public static final Float ln10 = new Float(10).ln_s();
public static final Float zero = new Float(0);

2。字段和构造函数

long v;
public Float(Float f) {
    v = f.v;
}
public Float(String val) {
    v = MathFP.toFP(val);
}
public Float(int val) {
    v = MathFP.toFP(val);
}
private Float(long val) {
    v = val;
}

最后一个构造函数相当与clone的意思。

3。函数的封装(我把基本运算也归到里面了)
一开始我是这么做的,比如add函数:

public Float add(Float b) {
    return new Float(MathFP.add(v, b.v));
}
public Float add(int b) {
    return new Float(MathFP.add(v, MathFP.toFP(b)));
}

大家看出什么问题来了吗?
如果要做一个x+1+2+3+4的运算,通过调用x.add(1).add(2).add(3).add(4)
将会生成4个Float对象,而其中的3个Float对象用过就扔掉了。
这使gc的负担飚升。于是我增加了这样一个方法:

public Float add_s(Float b) {
    v = MathFP.add(v, b.v);
    return this;
}

相当于+=的功能,于是可以调用x.add(1).add_s(2).add_s(3).add_s(4)来实现
这样就节省了3个Float的开销。其他的函数类推就不罗索了,下面看看FloatBox。

既然有了浮点数,我们如何输入呢?文本框有数字模式但是不支持浮点数,
用any模式?这样太不专业了,于是就有了FloatBox。

这就是整个实现:

package vmlinux.math;

import javax.microedition.lcdui.*;
import vmlinux.app.*;

public class FloatBox extends Canvas {

    public static final String[] Keypad = new String[] {
                                          "1", "2", "3",
                                          "4", "5", "6",
                                          "7", "8", "9",
                                          ".", "0", "+/-"
    };
    public Command Done;
    public Command Cancel;
    public Command Delete;
    StringBuffer val_;
    boolean dot_;
    Image imgKeypad_;
    char c_;

    public FloatBox(CommandListener o) {
        Cancel = new Command(StringManager.get("FloatBox.Cancel"),
                             Command.SCREEN, 3);
        Done = new Command(StringManager.get("FloatBox.Done"), Command.SCREEN,
                           2);
        Delete = new Command(StringManager.get("FloatBox.Delete"),
                             Command.SCREEN, 1);
        this.addCommand(Cancel);
        this.addCommand(Done);
        this.addCommand(Delete);
        this.setCommandListener(o);
        val_ = new StringBuffer("0");
        dot_ = false;
    }

    protected void paint(Graphics g) {
        g.setColor(0xff, 0xff, 0xff);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0x00, 0x00, 0x00);
        g.drawRect(5, 5, getWidth() - 10, 30);
        g.setColor(0x00, 0x00, 0xff);
        g.drawString(val_.toString(), getWidth() - 10, 10,
                     Graphics.TOP | Graphics.RIGHT);
        drawKeypad(Keypad, 40, g, c_);
    }

    void drawKeypad(String[] keys, int ytake, Graphics gx, char chr) {
        int xs = getWidth() / 3;
        int ys = (getHeight() - ytake) / 4;
        int hcenter = Graphics.TOP | Graphics.HCENTER;
        if (imgKeypad_ == null) {
            imgKeypad_ = Image.createImage(getWidth(), getHeight() - ytake);
            Graphics g = imgKeypad_.getGraphics();
            int c = 0;
            for (int j = 0; j < 4; ++j) {
                for (int i = 0; i < 3; ++i) {
                    g.setColor(0xcc, 0xcc, 0xcc);
                    g.drawRect((xs + 1) * i, (ys + 1) * j, xs - 2, ys - 2);
                    if (c < keys.length) {
                        g.setColor(0x00, 0x00, 0x00);
                        g.drawString(keys[c++], xs * i + xs / 2 - 2,
                                     ys * j + ys / 2 - 8, hcenter);
                    }
                }
            }
        }
        gx.drawImage(imgKeypad_, 0, ytake, Graphics.TOP | Graphics.LEFT);
        for (int i = 0; i < keys.length; ++i) {
            if (keys[i].indexOf(chr) >= 0) {
                gx.setColor(0xbb, 0xbb, 0xbb);
                gx.fillRect((xs + 1) * (i % 3), (ys + 1) * (i / 3) + ytake,
                            xs - 2, ys - 2);
                gx.setColor(0xff, 0xff, 0xff);
                gx.drawString(keys[i], xs * (i % 3) + xs / 2,
                              ys * (i / 3) + ytake + ys / 2 - 5, hcenter);
                break;
            }
        }
    }

    protected void keyPressed(int key) {
        if (key == Canvas.KEY_NUM0) {
            if (val_.length() == 0 ||
                (val_.length() > 0 && val_.charAt(0) != '0')) {
                val_.append('0');
            }
            c_ = '0';
        } else if (key >= Canvas.KEY_NUM1 && key <= Canvas.KEY_NUM9) {
            char c = (char) ('1' + key - Canvas.KEY_NUM1);
            if (val_.length() == 1 && val_.charAt(0) == '0') {
                val_.deleteCharAt(0);
                val_.append(c);
            } else {
                val_.append(c);
            }
            c_ = c;
        } else if (key == Canvas.KEY_STAR) {
            if (!dot_) {
                val_.append('.');
                dot_ = true;
            }
            c_ = '.';
        } else if (key == Canvas.KEY_POUND) {
            if (val_.length() > 0 && val_.charAt(0) == '-') {
                val_.deleteCharAt(0);
            } else if (val_.length() != 1 || val_.charAt(0) != '0') {
                val_.insert(0, '-');
            }
            c_ = '-';
        } else if (this.getGameAction(key) == Canvas.LEFT) {
            delete();
        }
        repaint();
    }

    public void delete() {
        if (val_.length() > 0) {
            if (val_.charAt(val_.length() - 1) == '.') {
                dot_ = false;
            }
            val_.deleteCharAt(val_.length() - 1);
            if (val_.length() == 1 && val_.charAt(0) == '-') {
                val_.deleteCharAt(0);
            }
        }
        if (val_.length() == 0) {
            val_.append('0');
        }
    }

    public Float getValue() {
        return new Float(val_.toString());
    }

    public void setValue(Float x) {
        val_.delete(0, val_.length());
        val_.append(x.toString());
    }
}

没什么难度,不多说了。StringManager参见我的另一篇字符串管理的文章。
样子很丑,看起来就像一个计算器。

有什么意见或建议请联系vmlinuxx@gmail.com,共同学习,共同进步:)