快速业务通道

Java Math 类中的新功能,第 2 部分: 浮点数 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-17
urn -magnitude;    }    else if (sign > 0) {    if (magnitude < 0) return -magnitude;    else return magnitude;    }    return magnitude; }

不过,真正的实现如清单 5 所示:

清单 5. 来自 sun.misc.FpUtils 的真正算法

public static double rawCopySign(double magnitude, double sign) {    return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) &                  (DoubleConsts.SIGN_BIT_MASK)) |                  (Double.doubleToRawLongBits(magnitude) &                  (DoubleConsts.EXP_BIT_MASK |                  DoubleConsts.SIGNIF_BIT_MASK))); }

仔细观察这些位就会看到,NaN 标记被视为正的。严格来说,Math.copySign() 并不对此 提供保证,而是由 StrictMath.copySign() 负责,但在现实中,它们都调用相同的位处理代 码。

清单 5 可能会比清单 4 快一些,但它的主要目的是正确处理负 0。Math.copySign(10, -0.0) 返回 -10,而 Math.copySign(10, 0.0) 返回 10.0。清单 4 中最简单形式的算法在 两种情况中都返回 10.0。当执行敏感的操作时,比如用极小的负双精度数除以极大的正双精 度数,就可能出现负 0。例如,-1.0E-147/2.1E189 返回负 0,而 1.0E-147/2.1E189 返回 正 0。不过,使用 == 比较这两个值时,它们是相等的。因此,如果要区分它们,必须使用 Math.copySign(10, -0.0) 或 Math.signum()(调用 Math.copySign(10, -0.0))来执行比 较。

Java Math 类中的新功能,第 2 部分: 浮点数(6)

时间:2011-04-30 IBM Elliotte Rusty Harol

对数和指数

指数函数是一个很好的例子,它表明处理有限精度浮点数(而不是无限精度实数)时是需 要非常小心的。在很多等式中都出现 ex(Math.exp())。例如,它可用于定义 cosh 函数,这已经在 第 1 部分中 讨论:

cosh(x) = (ex + e-x)/2

不过,对于负值的 x,一般是 -4 以下的数字,用于计算 Math.exp() 的算法表现很差, 并且容易出现舍入错误。使用另一个算法计算 ex - 1 会更加精确,然后在最终 结果上加 1。Math.expm1() 能够实现这个不同的算法(m1 表示 “减 1”)。例如,清单 6 给出的 cosh 函数根据 x 的大小在两个算法之间进行切换:

清单 6. cosh 函数

public static double cosh(double x) {    if (x < 0) x = -x;    double term1 = Math.exp(x);    double term2 = Math.expm1(-x) + 1;    return (term1 + term2)/2; }

这个例子有些呆板,因为在 Math.exp() 与 Math.expm1() + 1 之间的差别很明显的情况 下,常常使用 ex,而不是 e-x。不过,Math.expm1() 在带有多种 利率的金融计算中是非常实用的,比如短期国库券的日利率。

Math.log1p() 与 Math.expm1() 刚好相反,就像 Math.log() 与 Math.exp() 的关系一 样。它计算 1 的对数和参数(1p 表示 “加 1”)。在值接近 1 的数字中使用这个函数。 例如,应该使用它计算 Math.log1p(0.0002),而不是 Math.log(1.0002)。

现在举一个例子,假设您需要知道在日利率为 0.03 的情况下,需要多少天投资才能使 $1,000 增长到 $1,100。清单 7 完成了这个计算任务:

清单 7. 计算从当前投资额增长到未来特定值所需的时间

public static double calculateNumberOfPeriods(      double presentValue, double futureValue, double rate) {    return (Math.log(futureValue) - Math.log(presentValue))/Math.log1p (rate); }

在这个例子中,1p 的含义是很容易理解的,因为在计算类似数据的一般公式中通常出现 1+r。换句话说

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号