2010年3月13日土曜日

浮動小数点数 のビット構造が気になったので

AndroidのOpenGL ESプログラミングしていて
ふとJavaの浮動小数点数 (Floating point numbers)のビット構造が気になったので、
脱線して適当にテストプログラムを作成してみた。


【ソース】
public class FloatingPoint3 {

    float val = 0;

    String bits;         //
    String sign;         // 符号
    String exponent;     // 指数
    String mantissa;     // 仮数


    private static int floatsize = 32; // floatのビットサイズ
    public String getBitStr() {
        return bits;
    }

    public float getVal() {
        return val;
    }

    public void setVal(float val) {
        this.val = val;

        int bitval = Float.floatToRawIntBits(this.val);
        // System.out.println("i >>>" + i);

        StringBuffer sbf = new StringBuffer();
        // String str = Integer.toBinaryString(bitval);
        sbf.append(Integer.toBinaryString(bitval));
        int addlen = floatsize - sbf.length();
        for (int i = 0; i < addlen; i++) {
            sbf.insert(0, '0');
        }

        bits = sbf.toString();

    }

    public String getSign() {
        return bits.substring(0,1);
    }

    public String getExponent() {
        return bits.substring(1,9);
    }

    public String getMantissa() {
        return bits.substring(9,32);
    }

    // 指数の値取得
    public int getExponentVal() {
        int exponent_maxsize = 8;
        String    src = getExponent();
        int    r = 0;
        for(int i=0;i<src.length();i++){
            if(src.charAt(i) == '1'){
                r += 0x01 << ((exponent_maxsize-1) - i);
            }
        }
        r = r - 127;    // 指数部 は、0111 1111=127 で 0乗なので
        return    r;
    }
  
  
}


package com.naozary.test.FloatingPoint;
import java.util.Formatter;
public class FloatingPoint4 {

    float val = 0;
    int        bits;         //

    public int getBit() {
        return bits;
    }

    public float getVal() {
        return val;
    }

    public void setVal(float val) {
        this.val = val;
        bits = Float.floatToRawIntBits(this.val);
    }

    // 符号
    public int getSign() {
        return (bits >> 31) & 0x01;
    }

    // 指数
    public int getExponent() {
        return (bits >> 23) & 0xff;
    }

    // 仮数
    public int getMantissa() {
        return bits & 0x7fffff;
    }

    // 指数の値取得
    public int getExponentVal() {
        return getExponent() - 127;    // 指数部 は、0111 1111=127 で 0乗なので
    }
  
  
    public String toString() {
        StringBuffer    sbf = new StringBuffer();
        sbf.append(getFormatStr("%f = 0x%08X \n",val,bits));
        sbf.append(getFormatStr("符号 : %d \n",getSign()));
        sbf.append(getFormatStr("指数 : 0x%02X (=%d) \n",getExponent(),getExponentVal()));
        sbf.append(getFormatStr("仮数 : 0x%06X \n",getMantissa()));
        return    sbf.toString();      
    }
  
    // 固定小数点数(上位2バイト:整数部分 下位2バイト:少数部分)
    public int getFixedPointNumber() {
        int    n = 0;
      
        n = 0x800000 | getMantissa();        // ヒドンビットを付加
      
        int e = 7;        // 指数が0でも左に7シフトさせなければならない  
        e = e - getExponentVal();      
        n = n >> e;        // 少数点位置を合わせる
        n = getSign() == 1 ? -n : n;        // 符号を考慮
        return n;
    }
      
  
    public String    getFormatStr(String arg0,Object... args) {
        StringBuilder builder = new StringBuilder();
        Formatter formatter = new Formatter(builder);
        formatter.format(arg0,args);
        return    formatter.out().toString();      
      
    }
}


 
package com.naozary.test.FloatingPoint;


省略


public class TestFloat  extends JApplet implements ActionListener {



省略



    public void case001() {
        printf("********** %s() ********** \n",Thread.currentThread().getStackTrace()[1].getMethodName());

        FloatingPoint3 fp = new FloatingPoint3();

        fp.setVal(10.75F);
        disp(fp);

        fp.setVal(-10.75F);
        disp(fp);

        fp.setVal(0.33333F);
        disp(fp);

        fp.setVal(0.66666F);
        disp(fp);

        fp.setVal(0.0F);
        disp(fp);

        fp.setVal(1F);
        disp(fp);
      
        fp.setVal(2F);
        disp(fp);

        fp.setVal(3F);
        disp(fp);
  
        fp.setVal(4F);
        disp(fp);

  
        fp.setVal(5.5F);
        disp(fp);
      
        fp.setVal(0.55F);
        disp(fp);
      
      
    }

    public void case002() {
        printf("********** %s() ********** \n",Thread.currentThread().getStackTrace()[1].getMethodName());

        FloatingPoint4 fp = new FloatingPoint4();

        fp.setVal(10.75F);
        printf(fp.toString());
        printf("\n");

        fp.setVal(-10.75F);
        printf(fp.toString());
        printf("\n");
      
        fp.setVal(0.33333F);
        printf(fp.toString());
        printf("\n");
      
        fp.setVal(0.66666F);
        printf(fp.toString());
        printf("\n");

        fp.setVal(0.0F);
        printf(fp.toString());
        printf("\n");
      
        fp.setVal(1F);
        printf(fp.toString());
        printf("\n");
      
        fp.setVal(2F);
        printf(fp.toString());
        printf("\n");

        fp.setVal(5.5F);
        printf(fp.toString());
        printf("\n");
      
        fp.setVal(0.55F);
        printf(fp.toString());
        printf("\n");
      
      
    }
  
  
    public void case003() {
        printf("********** %s() ********** \n",Thread.currentThread().getStackTrace()[1].getMethodName());

        FloatingPoint4 fp = new FloatingPoint4();
        fp.setVal(1F);
        printf(fp.toString());
        printf("固定少数点数:0x%08X \n",fp.getFixedPointNumber());
        // printf("固定少数点数:0x%08X \n",-fp.getFixedPointNumber());
        printf("\n");

        fp.setVal(-1F);
        printf(fp.toString());
        printf("固定少数点数:0x%08X \n",fp.getFixedPointNumber());
        printf("\n");
      
      
        fp.setVal(5.5F);
        printf(fp.toString());
        printf("固定少数点数:0x%08X \n",fp.getFixedPointNumber());
        printf("\n");
      
        fp.setVal(-5.5F);
        printf(fp.toString());
        printf("固定少数点数:0x%08X \n",fp.getFixedPointNumber());
        printf("\n");

      
        fp.setVal(0.33333F);
        printf(fp.toString());
        printf("固定少数点数:0x%08X \n",fp.getFixedPointNumber());
        printf("\n");

      
        fp.setVal(0.66666666F);
        printf(fp.toString());
        printf("固定少数点数:0x%08X \n",fp.getFixedPointNumber());
        printf("\n");
    }

  
    public void disp(FloatingPoint3 fp) {
        printf("%f = %s \n",fp.getVal(),fp.getBitStr());
        printf("符号 : %s \n", fp.getSign());
        printf("指数 : %s (=%d)\n", fp.getExponent(),fp.getExponentVal());
        printf("仮数 : %s \n", fp.getMantissa());
        // printf("fp.getExponentVal() >>>%d \n", fp.getExponentVal());
        printf("\n");
    }
  
    public static void main(String[] args) {
        TestFloat    t01 = new TestFloat();
        t01.case001();
        t01.case002();
        t01.case003();


    }

}





【実行結果】

0 件のコメント:

コメントを投稿