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

Java ME 中 Math.pow() 方法使用詳解(一)

     編輯:J2ME

使用 Java 開發移動設備應用時,可能需要特定 Java VM 未提供的數學方法。本文專門解決 Java ME 缺少「冪」方法 Math.pow() 的問題。我們將演示三種不同方法開發同一 ME 應用,並選出最佳編程方案。

討論此問題,先考察整數與分數冪參數,分析限於正實數。整數與小數冪問題的解集相對容易(不考慮指數符號)。大多數情況下使用示例問題 n = 8^(2/3),求出 n 的良好估計或實際解。若初始指數不可用,牛頓法與割線法不易編程。雖二分法可行,但我們關注傳統上較少探究的三種方法:幾何衰變算法、利用 Math.sqrt() 保證 11 次迭代內收斂、泰勒級數逼近對數並進行歐拉轉換。

產生整數解的 ME Math.pow() 方法

傳統 Math.pow() 包含底數與指數兩參數。假定均為整數,求 ME 中同參數可編程解。解法簡單,如示例 1:以指數值為指標運行乘法循環。

示例 1

int pow(int x, int y) { // 底數 x,指數 y (即 x^y)
    int z = x;
    for (int i = 1; i < y; i++) z *= x;
    return z;
}

若需非整數冪值,正實數簡單解可用 Math.log()。如 8^(2/3),利用 2/3 * ln(8) = 1.386294361,再取指數 e^1.386294361 = 4。但 Java ME 也不支援 Math.log()。無 Math.pow() 與 Math.log() 時,考慮樸素「強力」試探法,應用 Math.sqrt()、自然對數與歐拉數 e 的泰勒級數逼近求解。

使用幾何衰變算法作為強力解的 ME Math.pow()

Java ME 早期實現含 float、double 類型。現將參數改為 double。可能需在 Math.pow() 使用小數指數。第一種方法:幾何衰變算法的「強力」試探法。簡單說,衰變算法從大於已知解的值開始,應用某方法衰變該值直至極度逼近解(見示例 2 線性衰變演示)。我們演示幾何形式收斂。

示例 2

int n; // 假設 n 為我們要找的數的解
int varX = 1000; // 假設解 ≤ 1000
while (varX > 0) {
    varX -= 1; // 遞減 1
    if (varX == n) return varX;
}

從 1000 遞減至找到預期數字,假設為正整數。此類算法構成強力試探法基礎。

類似方法可應用於小數。假設要求 n = 8^(2/3)。衰變算法需先找合適起點,等於或大於解。對正實數正指數容易做到。對示例,對兩邊立方得 n^3 = 8^2 = 64。起始值變為 64,知道 n 必小於 64。此推導對任何正指數值同樣適用。設計循環產生 n 的「充分接近」解,見示例 3,適合所有正底數與正指數。

示例 3

double pow(double x, double y) { // 定義分數冪新方法
    int den = 1000; // 指定任意分母
    int num = (int)(y * den); // 找分子
    int s = (num / den) + 1;
    // 變數 s 提供乘冪,用於找起始搜尋值。如求 n = 8^(2/3),用 8^2 = 64 作為起始值。
    // 因分母設為任意高值,必須嘗試約分。找不超過基本資料類型限制的最高允許分數。
    double z = Double.MAX_VALUE;
    while (z >= Double.MAX_VALUE) {
        den -= 1; num = (int)(y * den); s = (num / den) + 1;
        z = x;
        for (int i = 1; i < num; i++) z *= x;
    }
    // 實現衰變算法找 n 值
    double n = x; // 定義 n 為 x 的返回值(估計值)
    for (int i = 1; i < s; i++) n *= x; // 找 n^s
    while (n > 0) { // 開始衰變循環
        double a = n; // n 的代理
        for (int i = 1; i < den; i++) a *= n; // 找 a = n^den
        double check1 = a - z;
        double check2 = z - a;
        if (check1 < 0.00001 || check2 > 0.00001) return n; // 比較 a 與 z,百萬分之一精度內返回 n
        n *= 0.999; // 每次迭代任意衰變 0.1%
    }
    return -1.0; // 未找到值
}

本示例演示衰變算法用法。n 值(解估計值)按 1% 強制遞減。可依精度要求調整此值。也可加入邏輯比較前後迭代解,若改善則繼續,若回歸則返回前一值。

此解僅處理正指數。若值為負如何?下文解決此意外情況。

處理負指數

假定向 Math.pow() 傳遞負指數。指數為負時,簡單方案:將底數轉為小數,使指數為正。如 8^-2 轉為 (1/8)^2。以可編程方式用底數 x 除 1,用 -1 乘 y(見示例 6)。

示例 6

if (y < 0) {
    x = (1 / x); // 底數轉為分數
    y *= -1;     // 指數變正
}

我們已討論 Java ME 估計冪函數的「強力」幾何衰變算法。讀者會注意到,對較大底數與指數分子組合,樸素試探法有效能問題。如 8^5/2 起始值 32,768,1% 衰變需 5,196 次迭代,遠非最優。謹記此事實且不提供改進試探搜尋算法,我們轉向二次逼近,提供更合理的迭代需求。

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