当前教程
数字
系列中的下一个

系列中的下一个: 字符

数字

 

数字

本节首先讨论 Number 类在 java.lang 包中,它的子类,以及您在使用这些类的实例而不是原始数字类型的情况。

本节还介绍了 PrintStreamDecimalFormat 类,它们提供用于写入格式化数字输出的方法。

最后,Math 类在 java.lang 中进行了讨论。它包含数学函数来补充语言中内置的运算符。此类具有用于三角函数、指数函数等的方法。

在处理数字时,大多数情况下您在代码中使用基本类型。例如

int i = 500;
float gpa = 3.65f;
byte mask = 0x7f;

但是,有理由使用对象代替基本类型,Java 平台为每个基本数据类型提供了包装类。这些类将基本类型“包装”在对象中。通常,包装由编译器完成——如果您在需要对象的地方使用基本类型,编译器会将基本类型装箱到其包装类中。类似地,如果您在需要基本类型的地方使用数字对象,编译器会为您拆箱对象。有关更多信息,请参阅自动装箱和拆箱部分

所有数字包装类都是抽象类 Number 的子类

The Number Class Hierarchy

数字类层次结构

注意:还有四个 Number 的子类,这里没有讨论。 BigDecimalBigInteger 用于高精度计算。 AtomicIntegerAtomicLong 用于多线程应用程序。

您可能使用 Number 对象而不是基本类型有三个原因

  1. 作为期望对象的函数的参数(通常用于操作数字集合)。
  2. 使用类定义的常量,例如 MIN_VALUEMAX_VALUE,它们提供数据类型的上限和下限。
  3. 使用类方法将值转换为其他基本类型,将值转换为字符串,以及在数字系统(十进制、八进制、十六进制、二进制)之间转换。

下表列出了 Number 类所有子类实现的实例方法。

以下方法将此 Number 对象的值转换为返回的基本数据类型。

以下方法将此 Number 对象与参数进行比较。

方法 equals(Object obj) 确定此数字对象是否等于参数。如果参数不为 null 并且是相同类型且具有相同数值的对象,则这些方法返回 true。对于 DoubleFloat 对象,有一些额外的要求,在 Java API 文档中进行了描述。

每个 Number 类都包含其他方法,这些方法对于将数字转换为字符串和从字符串转换为数字以及在数字系统之间转换很有用。下表列出了 Integer 类中的这些方法。其他 Number 子类的方法类似

方法 描述
static Integer decode(String s) 将字符串解码为整数。可以接受十进制、八进制或十六进制数字的字符串表示形式作为输入。
static int parseInt(String s) 返回一个整数(仅限十进制)。
static int parseInt(String s, int radix) 返回一个整数,给定十进制、二进制、八进制或十六进制(基数分别等于 10、2、8 或 16)数字的字符串表示形式作为输入。
String toString() 返回一个 String 对象,表示此 Integer 的值。
static String toString(int i) 返回一个 String 对象,表示指定的整数。
static Integer valueOf(int i) 返回一个 Integer 对象,保存指定基本类型的值。
static Integer valueOf(String s) 返回一个 Integer 对象,保存指定字符串表示形式的值。
static Integer valueOf(String s, int radix) 返回一个 Integer 对象,保存指定字符串表示形式的整数值,使用 radix 的值进行解析。例如,如果 s = "333" 且 radix = 8,则该方法返回八进制数 333 的十进制整数等效值。

 

格式化数字打印输出

之前您看到了使用 printprintln 方法将字符串打印到标准输出 System.out。由于所有数字都可以转换为字符串,因此您可以使用这些方法打印出字符串和数字的任意组合。但是,Java 编程语言还有其他方法,当包含数字时,这些方法允许您对打印输出进行更多控制。

Printf 和 Format 方法

java.io 包包含一个 PrintStream 类,它有两个格式化方法,您可以使用它们来替换 printprintln。这些方法,formatprintf,彼此等效。您一直在使用的熟悉的 System.out 恰好是一个 PrintStream 对象,因此您可以在 System.out 上调用 PrintStream 方法。因此,您可以在代码中的任何地方使用 formatprintf,您之前一直在使用 printprintln。例如,

System.out.format(.....);

这两个 java.io.PrintStream 方法的语法相同

public PrintStream format(String format, Object... args)

其中 format 是一个字符串,指定要使用的格式,而 args 是使用该格式打印的变量列表。一个简单的例子是

System.out.format("The value of " + "the float variable is " +
     "%f, while the value of the " + "integer variable is %d, " +
     "and the string is %s", floatVar, intVar, stringVar); 

第一个参数,format,是一个格式字符串,指定了第二个参数中对象的格式化方式,argsformat 字符串包含纯文本以及格式说明符,它们是用于格式化 Object... args 参数的特殊字符。(Object... args 的表示法称为 *varargs*,这意味着参数的数量可以变化。)

格式说明符以百分号 (%) 开头,以转换符结尾。转换符是一个字符,表示要格式化的参数类型。在百分号 (%) 和转换符之间,可以包含可选的标志和说明符。有很多转换符、标志和说明符,它们在 java.util.Formatter 中有详细说明。

以下是一个基本示例

int i = 461012;
System.out.format("The value of i is: %d%n", i)

%d 指定单个变量是十进制整数。%n 是一个与平台无关的换行符。输出结果为

The value of i is: 461012

printfformat 方法是重载的。每个方法都有一个具有以下语法的版本

public PrintStream format(Locale l, String format, Object... args)

例如,要以法语系统(在英语表示的浮点数中,使用逗号代替小数点)打印数字,可以使用

System.out.format(Locale.FRANCE,
    "The value of the float " + "variable is %f, while the " +
    "value of the integer variable " + "is %d, and the string is %s%n", 
    floatVar, intVar, stringVar);

示例

下表列出了在示例程序 TestFormat.java 中使用的一些转换符和标志,该程序位于表格之后。

转换符 标志 说明
d 十进制整数。
f 浮点数。
n 适合运行应用程序的平台的换行符。应始终使用 %n,而不是 \n
tB 日期和时间转换 - 与语言环境相关的月份全名。
td, te 日期和时间转换 - 月份中的两位数日期。td 具有必要的首位零,te 没有。
ty, tY 日期和时间转换 - ty = 两位数年份,tY = 四位数年份。
tl 日期和时间转换 - 12 小时制中的小时。
tM 日期和时间转换 - 两位数的分钟,必要时具有首位零。
tp 日期和时间转换 - 与语言环境相关的上午/下午(小写)。
tm 日期和时间转换 - 两位数的月份,必要时具有首位零。
tD 日期和时间转换 - 日期为 %tm%td%ty
08 宽度为八个字符,必要时具有首位零。
+ 包含符号,无论是正数还是负数。
, 包含与语言环境相关的分组字符。
- 左对齐。
.3 小数点后三位。
10.3 宽度为十个字符,右对齐,小数点后三位。

以下程序展示了可以使用 format 进行的一些格式化操作。输出结果在嵌入式注释中用双引号括起来

import java.util.Calendar;
import java.util.Locale;

public class TestFormat {
    
    public static void main(String[] args) {
      long n = 461012;
      System.out.format("%d%n", n);      //  -->  "461012"
      System.out.format("%08d%n", n);    //  -->  "00461012"
      System.out.format("%+8d%n", n);    //  -->  " +461012"
      System.out.format("%,8d%n", n);    // -->  " 461,012"
      System.out.format("%+,8d%n%n", n); //  -->  "+461,012"
      
      double pi = Math.PI;

      System.out.format("%f%n", pi);       // -->  "3.141593"
      System.out.format("%.3f%n", pi);     // -->  "3.142"
      System.out.format("%10.3f%n", pi);   // -->  "     3.142"
      System.out.format("%-10.3f%n", pi);  // -->  "3.142"
      System.out.format(Locale.FRANCE,
                        "%-10.4f%n%n", pi); // -->  "3,1416"

      Calendar c = Calendar.getInstance();
      System.out.format("%tB %te, %tY%n", c, c, c); // -->  "May 29, 2006"

      System.out.format("%tl:%tM %tp%n", c, c, c);  // -->  "2:34 am"

      System.out.format("%tD%n", c);    // -->  "05/29/06"
    }
}

注意:本节中的讨论仅涵盖 formatprintf 方法的基础知识。更多详细信息可以在本教程的基本 I/O 部分的“格式化”页面中找到。使用 String.format() 创建字符串在 Strings 中有介绍。

 

DecimalFormat 类

可以使用 java.text.DecimalFormat 类来控制前导零和尾随零、前缀和后缀、分组(千位)分隔符和小数分隔符的显示。 DecimalFormat 在数字格式化方面提供了很大的灵活性,但它可能会使代码变得更加复杂。

以下示例通过将模式字符串传递给 DecimalFormat 构造函数来创建一个 DecimalFormat 对象 myFormatter。然后,myFormatter 调用 format 方法(DecimalFormatNumberFormat 继承了该方法) - 它接受一个双精度值作为参数,并以字符串形式返回格式化的数字。

以下是一个示例程序,演示了 DecimalFormat 的用法

import java.text.*;

public class DecimalFormatDemo {

   static public void customFormat(String pattern, double value ) {
      DecimalFormat myFormatter = new DecimalFormat(pattern);
      String output = myFormatter.format(value);
      System.out.println(value + "  " + pattern + "  " + output);
   }

   static public void main(String[] args) {

      customFormat("###,###.###", 123456.789);
      customFormat("###.##", 123456.789);
      customFormat("000000.000", 123.78);
      customFormat("$###,###.###", 12345.67);  
   }
}

输出结果为

123456.789  ###,###.###  123,456.789
123456.789  ###.##  123456.79
123.78  000000.000  000123.780
12345.67  $###,###.###  $12,345.67

下表解释了每行输出结果。

模式 输出结果 说明
123456.789 ###,###.### 123,456.789 磅符号 (#) 表示数字,逗号是分组分隔符的占位符,句点是十进制分隔符的占位符。
123456.789 ###.## 123456.79 value 的小数点后有三位数字,但模式只有两位。format 方法通过四舍五入来处理这种情况。
123.78 000000.000 000123.780 pattern 指定了前导零和尾随零,因为使用了 0 字符而不是磅符号 (#)。
12345.67 $###,###.### $12,345.67 pattern 中的第一个字符是美元符号 ($)。请注意,它紧接在格式化后的 output 中的最左侧数字之前。

 

超越基本算术

Java 编程语言使用其算术运算符支持基本算术运算:+-*/%Math 类位于 java.lang 包中,提供了用于执行更高级数学计算的方法和常量。

Math 类中的所有方法都是静态的,因此可以直接从类中调用它们,例如

Math.cos(angle);

注意:使用静态导入语言功能,您不必在每个数学函数前面写 Mathimport static java.lang.Math.*; 这允许您通过简单名称调用 Math 类方法。例如:cos(angle);

常量和基本方法

Math 类包含两个常量

  • Math.E,它是自然对数的底,以及
  • Math.PI,它是圆周长与其直径之比。

Math 类还包含 40 多个静态方法。下表列出了一些基本方法。

计算绝对值

舍入值

计算最小值

计算最大值

以下程序 BasicMathDemo 演示了如何使用其中的一些方法

public class BasicMathDemo {
    public static void main(String[] args) {
        double a = -191.635;
        double b = 43.74;
        int c = 16, d = 45;

        System.out.printf("The absolute value " + "of %.3f is %.3f%n", 
                          a, Math.abs(a));

        System.out.printf("The ceiling of " + "%.2f is %.0f%n", 
                          b, Math.ceil(b));

        System.out.printf("The floor of " + "%.2f is %.0f%n", 
                          b, Math.floor(b));

        System.out.printf("The rint of %.2f " + "is %.0f%n", 
                          b, Math.rint(b));

        System.out.printf("The max of %d and " + "%d is %d%n",
                          c, d, Math.max(c, d));

        System.out.printf("The min of of %d " + "and %d is %d%n",
                          c, d, Math.min(c, d));
    }
}

以下是该程序的输出结果

The absolute value of -191.635 is 191.635
The ceiling of 43.74 is 44
The floor of 43.74 is 43
The rint of 43.74 is 44
The max of 16 and 45 is 45
The min of 16 and 45 is 16

指数和对数方法

下表列出了 Math 类的指数和对数方法。

以下程序 ExponentialDemo 显示了 e 的值,然后对任意选择的数字调用上表中列出的每个方法

public class ExponentialDemo {
    public static void main(String[] args) {
        double x = 11.635;
        double y = 2.76;

        System.out.printf("The value of " + "e is %.4f%n",
                          Math.E);

        System.out.printf("exp(%.3f) " + "is %.3f%n",
                          x, Math.exp(x));

        System.out.printf("log(%.3f) is " + "%.3f%n",
                          x, Math.log(x));

        System.out.printf("pow(%.3f, %.3f) " + "is %.3f%n",
                          x, y, Math.pow(x, y));

        System.out.printf("sqrt(%.3f) is " + "%.3f%n",
                          x, Math.sqrt(x));
    }
}

以下是运行 ExponentialDemo 时将看到的输出结果

The value of e is 2.7183
exp(11.635) is 112983.831
log(11.635) is 2.454
pow(11.635, 2.760) is 874.008
sqrt(11.635) is 3.411

三角函数方法

Math 类还提供了一组三角函数,在下表中进行了总结。传递给每个方法的值是以弧度表示的角度。可以使用 toRadians(double d) 方法将度数转换为弧度。

以下是一个名为 TrigonometricDemo 的程序,它使用这些方法中的每一个来计算 45 度角的各种三角函数值。

public class TrigonometricDemo {
    public static void main(String[] args) {
        double degrees = 45.0;
        double radians = Math.toRadians(degrees);
        
        System.out.format("The value of pi " + "is %.4f%n",
                           Math.PI);

        System.out.format("The sine of %.1f " + "degrees is %.4f%n",
                          degrees, Math.sin(radians));

        System.out.format("The cosine of %.1f " + "degrees is %.4f%n",
                          degrees, Math.cos(radians));

        System.out.format("The tangent of %.1f " + "degrees is %.4f%n",
                          degrees, Math.tan(radians));

        System.out.format("The arcsine of %.4f " + "is %.4f degrees %n", 
                          Math.sin(radians), 
                          Math.toDegrees(Math.asin(Math.sin(radians))));

        System.out.format("The arccosine of %.4f " + "is %.4f degrees %n", 
                          Math.cos(radians),  
                          Math.toDegrees(Math.acos(Math.cos(radians))));

        System.out.format("The arctangent of %.4f " + "is %.4f degrees %n", 
                          Math.tan(radians), 
                          Math.toDegrees(Math.atan(Math.tan(radians))));
    }
}

该程序的输出如下所示。

The value of pi is 3.1416
The sine of 45.0 degrees is 0.7071
The cosine of 45.0 degrees is 0.7071
The tangent of 45.0 degrees is 1.0000
The arcsine of 0.7071 is 45.0000 degrees
The arccosine of 0.7071 is 45.0000 degrees
The arctangent of 1.0000 is 45.0000 degrees

 

随机数

random() 方法返回一个介于 0.0 和 1.0 之间的伪随机数。范围包括 0.0 但不包括 1.0。换句话说:0.0 <= Math.random() < 1.0。要获得不同范围内的数字,可以对 random 方法返回的值进行算术运算。例如,要生成一个介于 0 和 9 之间的整数,可以这样写:

int number = (int)(Math.random() * 10);

通过将值乘以 10,可能的取值范围变为 0.0 <= number < 10.0

当需要生成单个随机数时,使用 Math.random 非常有效。如果需要生成一系列随机数,则应创建一个 java.util.Random 实例,并调用该对象上的方法来生成数字。


上次更新: 2021 年 9 月 14 日


当前教程
数字
系列中的下一个

系列中的下一个: 字符