首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

CLDC 1.0 無 float 支援:定點數與 IEEE 754 軟實現

     編輯:J2ME

前言

CLDC 1.0 移除 float/double 以減小 VM 體積。若需浮點運算 (物理模擬、3D、GPS 計算),有三條路:

  1. 定點數:整數模擬小數,效能最高,精度固定
  2. IEEE 754 軟浮點:手工解析 int bits 為符號/指數/尾數,通用但慢
  3. 升級 CLDC 1.1:原生支援 float (現代機型普遍支援)

本文提供後兩者實現代碼與效能分析。

方案一:IEEE 754 單精度軟解析 (intBitsToFloat)

將 32-bit int 視為 IEEE 754 二進制佈局:

  • Bit 31:符號位 (S)
  • Bit 30~23:指數位 (E,偏移 127)
  • Bit 22~0:尾數位 (M,隱含最高位 1)

值 = (-1)^S × 1.M × 2^(E-127)

/**
 * 將 IEEE 754 int bits 轉為 整數部分 + 小數部分(放大1000倍)
 * @param bits 32-bit IEEE 754 表示
 * @param precision 0=小數3位(×1000), 1=小數2位(×100) 等
 * @return int[2] { 整數部分, 小數部分(已放大) }
 */
public static int[] intBitsToFloat(int bits, int precision) {
    // 1. 符號
    int sign = (bits >> 31) & 1;

    // 2. 指數 (無偏移)
    int exp = ((bits >> 23) & 0xFF) - 127;

    // 3. 尾數 (含隱含位 1)
    int mantissa = (bits & 0x7FFFFF) | 0x800000; // 23 bits + 隱含 1 = 24 bits

    // 4. 根據指數左移/右移尾數對齊二進制小數點
    if (exp >= 0) mantissa <<= exp;      // 整數部分增大
    else          mantissa >>= -exp;     // 變為小數

    // 5. 分離整數與小數 (以 2^23 為單位)
    int intPart = mantissa >> 23;
    int fracPart = mantissa & 0x7FFFFF; // 剩餘 23 bits 為小數

    // 6. 小數轉十進制 (放大 precision 指定倍數)
    int scale = (precision == 0) ? 1000 : 100; // 可擴充
    long fracScaled = (fracPart * (long)scale) >> 23; // 定點數乘法再歸一化

    // 7. 符號處理
    if (sign == 1) { intPart = -intPart; fracScaled = -fracScaled; }

    return new int[] { intPart, (int)fracScaled };
}

使用範例

// 網路位元組序 (Big Endian) 讀取 4 bytes 組裝 int
byte[] bb = ...; // 來自 Socket/HTTP
int bits = ((bb[0]&0xFF)<<24) | ((bb[1]&0xFF)<<16) | ((bb[2]&0xFF)<<8) | (bb[3]&0xFF);

int[] result = intBitsToFloat(bits, 0); // 3 位小數
System.out.println("Value = " + result[0] + "." + String.format("%03d", Math.abs(result[1])));

方案二:定點數運算庫 (推薦遊戲/即時應用)

以 Q16.16 格式 (高 16 位整數、低 16 位小數) 為例:

public final class Fixed16 {
    public static final int ONE = 1 << 16; // 65536
    public static final int MASK = 0xFFFF;

    // 整數 → 定點數
    public static int toFixed(int i) { return i << 16; }
    public static int toFixed(float f) { return (int)(f * ONE); } // 僅編譯期/預處理用

    // 定點數 → 整數 (截斷/四捨五入)
    public static int toInt(int f) { return f >> 16; }
    public static int toIntRound(int f) { return (f + 0x8000) >> 16; }

    // 加減:直接整數加減
    public static int add(int a, int b) { return a + b; }
    public static int sub(int a, int b) { return a - b; }

    // 乘法:(a*b) >> 16,防溢位用 long
    public static int mul(int a, int b) {
        return (int)(((long)a * b) >> 16);
    }

    // 除法:(a<<16) / b
    public static int div(int a, int b) {
        return (int)(((long)a << 16) / b);
    }

    // 三角函數查表 (0~360 度,精度 1 度)
    private static final int[] SIN_TABLE = new int[361];
    private static final int[] COS_TABLE = new int[361];
    static {
        for (int i = 0; i <= 360; i++) {
            double rad = Math.toRadians(i);
            SIN_TABLE[i] = (int)(Math.sin(rad) * ONE);
            COS_TABLE[i] = (int)(Math.cos(rad) * ONE);
        }
    }
    public static int sin(int deg) { return SIN_TABLE[deg % 360]; }
    public static int cos(int deg) { return COS_TABLE[deg % 360]; }

    // 平方根 (牛頓法)
    public static int sqrt(int x) {
        if (x <= 0) return 0;
        int r = x >> 1; // 初猜
        for (int i = 0; i < 5; i++) // 5 次迭代足夠
            r = (r + div(x, r)) >> 1;
        return r;
    }
}

效能對比 (模擬器估算)

操作定點數軟浮點CLDC 1.1 原生 float
加減1~2 週期~50 週期1 週期
乘除~10 週期 (long)~100 週期2~5 週期
三角/開根查表/5次迭代極慢 (轉 float 再算)硬體/庫優化
精度固定 1/65536 (~1.5e-5)IEEE 754 單精度 (~7 位有效數字)同左

選型建議

  • 遊戲物理、粒子、骨骼動畫:定點數 (Q16.16 或 Q8.24 視範圍調整),配合查表
  • GPS 座標、地圖投影、科學計算:軟浮點或要求 CLDC 1.1 (現代機型均支援)
  • 網路協議解析浮點欄位:intBitsToFloat 單次轉換即可,不影響主迴圈
  • 混合策略:核心迴圈定點數,邊緣邏輯 (存檔、網路) 用軟浮點轉換

總結

CLDC 1.0 無 float 非絕對障礙。**定點數** 以極低開銷解決 90% 遊戲數學需求;**IEEE 754 軟解析** 處理外部浮點數據交互。現代 J2ME 開發應優先鎖定 CLDC 1.1 設備,獲得原生浮點支援,簡化代碼複雜度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved