• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jwcat313
博客园    首页    新随笔    联系   管理    订阅  订阅
Java核心技术卷1 第三章选读

前言

本文内容选自Java核心技术卷1 第10版,感兴趣的小伙伴可以自行阅读原书,以下内容为本人学习后摘取的片段与大家分享。

正文

3.3.2 浮点类型
所有的浮点数值计算都遵循 IEEE 754 规范。具体来说,下面是用于表示溢出和出错情况的三个特殊的浮点数值:

  • 正无穷大
  • 负无穷大
  • NaN (不是一个数字)

例如,一正整数除以 0 的结果为正无穷大。计算 0/0 或者负数的平方根结果为 NaN。

常量 Double_POSITIVE_INFINITY、 Double.NEGATIVEJNFINITY 和 Double.NaN ( 以及相应的 Float 类型的常量) 分别表示这三个特殊的值, 但在实际应用中很少遇到。
特别要说明的是, 不能这样检测一个特定值是否等于 Double.NaN:

if (x == Double.NaN) // is never true

所有“ 非数值” 的值都认为是不相同的。然而,可以使用 Double.isNaN 方法:

if (Double.isNaN(x)) // check whether x is "not a number"

警告: 浮点数值不适用于无法接受舍入误差的金融计算中。 例如,命令

System.out.println(2.0 - 1.1)

将打印出 0.8999999999999999, 而不是人们想象的 0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示, 而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确地表示分数 1/3 一样。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecimal 类。

并且,NaN类型也不等于自己,尝试运行以下代码:

System.out.println(Double.NaN == Double.NaN); // is false

3.5.1 数学函数与常量

在 Math类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。
要想计算一个数值的平方根, 可以使用 sqrt 方法:

double x = 4;
double y = Math.sqrt(x);
System.out.println(y); // prints 2.0

注释: println 方法和 sqrt 方法存在微小的差异。println 方法处理 System.out 对象。但是,Math 类中的 sqrt 方法处理的不是对象,这样的方法被称为静态方法。
在 Java中,没有幂运算, 因此需要借助于 Math 类的 pow 方法。语句:

double y = Math.pow(x, a);

将 y 的值设置为 x 的 a 次幂( xa)。pow 方法有两个 double 类型的参数, 其返回结果也为double 类型。

floorMod 方法的目的是解决一个长期存在的有关整数余数的问题。考虑表达式 n % 2。所有人都知道, 如果 n 是偶数, 这个表达式为 0 ; 如果 n 是奇数, 表达式则为 1。当然, 除非 n 是负数 如果 n 为负,这个表达式则为 -1。为什么呢? 设计最早的计算机时,必须有人制定规则,明确整数除法和求余对负数操作数该如何处理。数学家们几百年来都知道这样一个最优(或“ 欧几里德”)规则:余数总是要 ≥0。不过, 最早制定规则的人并没有翻开数学书好好研究,而是提出了一些看似合理但实际上很不方便的规则。

下面考虑这样一个问题: 计算一个时钟时针的位置。这里要做一个时间调整, 而且要归一化为一个 0 ~ 11 之间的数。 这很简单:(position + adjustment) % 12。不过, 如果这个调整为负会怎么样呢? 你可能会得到一个负数。所以要引入一个分支, 或者使用((position + adjustment) % 12 + 12) % 12。不管怎样, 总之都很麻烦。
floorMod 方法就让这个问题变得容易了:floorMod(position + adjustment, 12) 总会得到一个 0 ~ 11 之间的数。
(遗憾的是,对于负除数,floorMod 会得到负数结果,不过这种情况在实际中很少出现。)

3.5.2 数值类型之间的转换

经常需要将一种数值类型转换为另一种数值类型。图 3-1 给出了数值类型之间的合法转换。
在图 3-1 中有 6 个实心箭头,表示无信息丢失的转换;有 3 个虚箭头, 表示可能有精度损失的转换。 例如,123 456 789 是一个大整数, 它所包含的位数比 float 类型所能够表达的位数多。 当将这个整型数值转换为 float 类型时, 将会得到同样大小的结果,但却失去了一定的精度。

int n = 123456789;
float f = n; // f is 1.23456792E8

当使用上面两个数值进行二元操作时(例如 n + f,n 是整数, f 是浮点数,) 先要将两个操作数转换为同一种类型,然后再进行计算。

  • 如果两个操作数中有一个是 double 类型, 另一个操作数就会转换为 double 类型。
  • 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
  • 否则, 如果其中一个操作数是 long 类型, 另一个操作数将会转换为 long 类型。
  • 否则, 两个操作数都将被转换为 int 类型。
posted on 2024-12-16 10:16  九尾猫313  阅读(16)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3