java jfrme 输入域_Java ME中的Math.pow()方法使用详解(2)

使用 Math.sqrt() 方法的 ME Math.pow()

开发我们的 Math.pow() 方法的第二种方法是通过使用 Math.sqrt() 方法(参见示例 7)。使用Math.sqrt() 方法要求我们对具有偶分母的幂进行估计。例如,n = 82/3 => n3 = 82 是一个棘手问题,因为我们需要立方根,而非平方根。为了调整示例中的此问题,我们我们就对两端再求一次平方:n3 = 82 => n6 = 84。然后,我们就可以继续进行,恰好在两次迭代之内求出解。

当然,我们的 ME Math.pow() 方法的指数不会以分子和分母的形式开始,而是向我们传递一个实数。我们将此实数转换为具有偶分母的小数,然后利用相应的平方根数来对

n 求解。在我们的 n = 82/3 示例中,我们进行如下转换:

n = 82/3 => n = 8683/1024 => n1024 = 8683

我们选择 1024 作为分母,因为对平方根函数迭代 10 次将得到 n 的值。特别指出,(n1024)(1/(2^10)) = n。当然,我们可能需要根据方程右侧的大小来减少迭代次数。示例 7 演示了这种方法。

示例 7ouble pow(doublex,doubley)

{

//Convert the real power to a fractional form

intden =1024;//declare the denominator to be 1024

/*Conveniently 2^10=1024, so taking the square root 10

times will yield our estimate for n. In our example

n^3=8^2n^1024 = 8^683.*/

intnum = (int)(y*den);// declare numerator

intiterations =10;/*declare the number of square root

iterations associated with our denominator, 1024.*/

doublen = Double.MAX_VALUE;/* we initialize our

estimate, setting it to max*/

while( n >= Double.MAX_VALUE && iterations >1)

{

/* We try to set our estimate equal to the right

hand side of the equation (e.g., 8^2048). If this

number is too large, we will have to rescale. */

n = x;

for(inti=1; i 

/*here, we handle the condition where our starting

point is too large*/

if( n >= Double.MAX_VALUE )

{

iterations--;/*reduce the iterations by one*/

den = (int)(den /2);/*redefine the denominator*/

num = (int)(y*den);//redefine the numerator

}

}

/*************************************************

** We now have an appropriately sized right-hand-side.

** Starting with this estimate for n, we proceed.

**************************************************/

for(inti =0; i 

{

n = Math.sqrt(n);

}

// Return our estimate

returnn;

}

自然对数和欧拉 e 的泰勒级数逼近

对于正实数产生 Math.pow() 方法最简便的方式之一是链接几个方法,包括使用 泰勒级数。假定我们需要幂 y = xb。该式与 ln(y) = b*ln(x) 等价。进而,我们可以使用泰勒级数扩展估算 x 的自然对数,如下所示。ln(x) = (x-1) –(x-1)2/2+ (x-1)3/3- (x-1)4/4….if|x-1|<=1OR

ln(x) =1/(x/(x-1)) +1/(x/(x-1))2+1/(x/(x-1))3…if|x|>1

由于 x 为正,因而 x 的整个域为这些方程所覆盖。此交错级数可以提供对底数对数的非常接近的逼近。用指数乘以此对数将得到 ln(y),方程的右侧 ln(y)=b*ln(x)。现在,我们仅需求出 eln(y) 即可完成运算。我们使用另一个泰勒级数扩展来完成此过程:ex = 1 + x + x2 / 2! + x3 / 3! + … 使用这两个公式,即可求得问题的解,如示例 8 所示。

示例 8doublepow(doublea,doubleb)

{

// true if base is greater than 1

booleangt1 = (Math.sqrt((a-1)*(a-1)) <=1)?false:true;

intoc = -1;// used to alternate math symbol (+,-)

intiter =20;// number of iterations

doublep, x, x2, sumX, sumY;

// is exponent a whole number?

if( (b-Math.floor(b)) ==0)

{

// return base^exponent

p = a;

for(inti =1; i 

returnp;

}

x = (gt1)?

(a /(a-1)):// base is greater than 1

(a-1);// base is 1 or less

sumX = (gt1)?

(1/x):// base is greater than 1

x;// base is 1 or less

for(inti =2; i 

{

// find x^iteration

p = x;

for(intj =1; j 

doublexTemp = (gt1)?

(1/(i*p)):// base is greater than 1

(p/i);// base is 1 or less

sumX = (gt1)?

(sumX+xTemp):// base is greater than 1

(sumX+(xTemp*oc));// base is 1 or less

oc *= -1;// change math symbol (+,-)

}

x2 = b * sumX;

sumY =1+x2;// our estimate

for(inti =2; i <= iter; i++ )

{

// find x2^iteration

p = x2;

for(intj =1; j 

// multiply iterations (ex: 3 iterations = 3*2*1)

intyTemp =2;

for(intj = i; j >2; j-- )yTemp *= j;

// add to estimate (ex: 3rd iteration => (x2^3)/(3*2*1) )

sumY += p/yTemp;

}

returnsumY;// return our estimate

}

几乎在所有情况下,由泰勒级数逼近返回的估计比衰变算法方法更为精确,而 Math.sqrt() 也可以产生更好的结果。泰勒级数方法所使用的计算周期较少, 但在值趋于 0 时会不稳定。Math.sqrt() 结果可以提供良好的逼近,通常到第三位数字。有关使用多个任意分配的正实型变量的方法的比较,请参见表 1。我们可以看到,对于实际应用, Math.sqrt() 或泰勒级数方法对于是大多数值都比较优良。

表 1:衰变算法和平方根方法的比较

底数,指数 实际结果 泰勒级数逼近 Math.sqrt() 估计值 衰变算法估计值

8.0, 0.75 4.75682846 4.7423353221144557 4.75682846 4.751286816

8.0, 0.667 4.002774 3.9919355054959973 3.994588452 3.994453662

16.0, 8.0 4294967296 4294967296 4294967296 4294752931

32.0, 5.0 33554432 33554432 33554432 33553177.47

11.0, 3.0 1331 1331 1331 1330.967224

10.0, 10.0 10000000000 10000000000 10000000000 9999699608

77.0, 3.0 456533 456533 456533 456527.6254

5.0, 15.0 30517578125 30517578125 30517578125 30516279235

15.0, 9.0 38443359375 38443359375 38443359375 38440083836

3.0, 21.0 10460353203 10460353203 10460353203 10459907131

5.0, 0.05 1.083798387 1.0837883791740017 1.083457755 1.08205432

7.0, 0.37 2.054406 2.0529191207908064 2.050973357 2.051043668

1.5, 0.789 1.377006542 1.377006541546755 1.376496289 1.376798426

1.5, 3.789 4.647397078 4.647381683179335 4.64015972 4.644836289

0.06282, 0.325784 0.405919146 0.41327102396968585 0 0.06282

0.7261, 0.20574 0.936270645 0.9362706445348806 0.93646901 0.7261

0.903272, 0.48593 0.951767579 0.951767579257642 0.951823588 0.903272

0.821111, 0.767392 0.85963221 0.8596322100794738 0.859766145 0.821111

0.24352, .004322 0.99391353 0.9939136545397182 0.994497397 0.24352

0.000125, .99556 0.000130089 627097113.1963351 0 0.000125

编程注意事项和结论

本文已经解决了在 Java ME 中开发 Math.pow() 方法的三种途径。虽然朴素的“强力”几何衰变试探性方法比较不错,而且对于小问题可能很有用处,但是 Math.sqrt() 改写对于大多数范围的应用可能要好一些。最佳方法可能是泰勒级数逼近。显然,这三个示例均未包括完成该任务的特有方法(如二分法及参考资料中介绍的其他方法),并且我们希望其他方法可以提供占用较少资源的更为高效的技巧。最后需要注意的一点是:如果要求您开发此类方法,务必考虑其应用,所需的参数以及预期的结果和精度。

【编辑推荐】

【责任编辑:red7 TEL:(010)68476606】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值