一个初出茅庐的小子与大家共享一些关于Number和Math的使用,因水平有限,难免有写的不完善的地方,嘻嘻。看完之后,希望可以留下你珍贵的指导意见。
The Numbers Classes
在写代码的时候,也许会使用到java 各种的基本数据类型,如下:
int i = 500;
float gpa = 3.65f;
byte mask = 0xff;
然而,在面向对象开发的过程,我们更倡导你使用对象来代替各种的基本数据类型,而java也为各种基本数据类型提供了wrapper class(包装类)——这些wrapper class封装了对应的基本数据。通常,编译器会为我们完成这种封装——换句话说就是,如果一个方法需要Object类型的参数,而实际提供的值确实2、3等数值,这时编译器会把2、3等数值封装成对应的wrapper class;类似,如果一个方法需要基本数据类型的参数,而实际提供的却似Object类型,这时编译器会Object类型的参数拆成几本数据类型——而这就所为的“自动拆装箱原理”。
接着给出一个自动拆装箱的demo:
Integer x, y;
x = 12;
y = 15;
System.out.println(x+y);
以上为x、y变量赋int 值,编译器会自动将x、y封装成Integer对象类型;在println()里,为了进行基本的算术处理,编译器会自动将x、y变量拆成int的基本数据类型。
所有基本数据的wrapper class都是抽象类Number的子类
附:在这里,有四个Number的子类并没有讨论。BigDecimal 和 BigInteger 是用于高精度的运算;AtomicInteger 和 AtomicLong 用于多线程程序里。
下面给出使用wrapper class 而不使用基本数据类型的理由:
1、可用在需要Object类型参数的方法里(常用于操作集合的数据)
2、在类里可使用各种常量(如MIN_VALUE
和MAX_VALUE),可以提供各种数据的上下界限(范围)。
3、可以使用wrapper class的对象方法,进行各种值与基本数据类型的相互转换,如String类型的相互转换,还可以与各种进制的数据进行相互装换(二进制binary、八进制octal、十进制decimal、十六进制hexadecimal)
下表列出了各个wrapper class都具有的方法(Number 类的方法)
Methods Implemented by all Subclasses of Number | |
方法 | 描述 |
byte byteValue() | 将Number对象转换成对应的基本数据类型 |
int compareTo(Byte anotherByte) | 将Number对象的值与参数anotherXxx的值进行比较 |
boolean equals(Object obj) | 判断Number对象和参数Object是否相同。 当两个对象不为空且数据类型和值都一致的情况下,才返回true。 如果判断的是Double和Float类型,则还需要一些额外的参数,详情可参考java API的官方文档。 |
对于与String类型的数据与及各种进制数据之间的装换,每个Number类(在这指其子类)都有着相对应的方法。下表列出了Integer对象与String数据和进制之间相互转换的方法。其他的Number类都与之类似。
Integer类的转换方法 | |
方法 | 描述 |
static Integer decode(String s) | 将String解码为Integer。String数据可以是十进制、八进制或者十六进制。 |
static int parseInt(String s) | 返回一个int值,String只能是十进制的数据。 |
static int parseInt(String s, int radix) | 将指定进制的String数据转换成int值。参数radix指多少进制(可以是2、8、10或者16) |
String toString() | 将Integer数据转成String类型 |
static String toString(int i) | 返回一个指定整数的String对象 |
static Integer valueOf(int i) | 返回一个表示指定的int值的Integer实例。 |
static Integer valueOf(String s) | 返回String数据的Integer对象 |
static Integer valueOf(String s, int radix) | 将指定进制的String数据转换为Integer类型。如当s=”333”,radix=8时,会返回数据为219的Integer实例。 |
格式化输出各种数据
一直以来,也许你都是在使用标准输出(System.out)输出各种数据,之所以可以这样做,是因为所有Number数据都可以转换成String类型。然而,有时候你可能需要更好地控制数据的输出,则需要使用java提供的其他方法。
printf()和format()方法
在java.io包里,有一个PrintStream类,此类提供了两个方法(printf()和format())来取代print()和println()。printf和format方法除了名字不一样之外,其余用法一致。同时因为System.out本事是一个PrintStream对象,所以你可以在原来使用print()和println()的位置用printf()或者format()方法来代替——System.out.format(.....);
其方法原型如下:
public PrintStream format(String format, Object... args);
public PrintStream printf(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);
格式说明由“%+转换符”组成,转换符是一个指定输出数据类型的字符。同时,你可以在“%”和转换符之间有选择地添加其他标记。想了解更多关于转换符标记的信息,可以参阅java.util.Formatter
。下面给出一个基本用法的例子:
int i = 461012;
System.out.format("The value of i is: %d%n", i);
“%d”代表了十进制数据(在这里值i),“%n”代表了输出换行,所以其输出如下:
The value of i is: 461012
为了适应各地语言的使用习惯,java重载了printf和format方法,如下:
public PrintStream format(Locale l, String format, Object... args)
如在法国,输出的带有小数的数据时,是用“,”划分整数和小数的,如下面的代码:
float floatVar = 123.37f;
int intVar = 123;
StringstringVar = "123";
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);
其输出如下:
The value of the float variable is 123,370003, while the value of the integer variable is 123, and the string is123
Demo:格式化输出
在这个Demo里,使用到各种常用的转化符和flags,具体解释如下表:(更多格式可参阅java.util.Formatter)
Converters and Flags Used indemo.java | ||
转换符 | Flag | 说明 |
d | 十进制数据 | |
f | 浮点数据 | |
n | 换行符。注意是用“%n”,而不是“\n”. | |
tB,tb | ‘t’指日期/时间的转换(下同),’B’指月份全称(如January),’b’指月份的简称(如Jan) | |
ty, tY | 格式年份,‘y’指格式化时带前导零的两位数,即00 – 99;’Y’指格式化时带前导零的四位数(至少),如0096或者2013。 | |
tm | 格式月份,’m’指格式时带前导零的两位数,即01 ~ 13. | |
td, te | ‘t’指日期/时间的转换,’d’指一个月中的天数,在格式化时带前导零的两位数,即01 – 31;‘e’指格式化为两位数,即1 – 31。 | |
tl,tk | 格式小时数,’l’指12小时制(1 ~ 12),’k’指24小时制(0 ~ 23)。 | |
tM | 格式分钟数,’M’指格式化时带前导零的两位数,即00 ~ 59。 | |
tS | 格式化秒,格式化时带前导零的两位数,即00 - 60("60" 是支持闰秒所需的一个特殊值)。 | |
tp | 特定于语言环境的上午或下午,标记以小写形式表示,例如 "am" 或 "pm"。 | |
tD | A date & time conversion—date as %tm%td%ty | |
08 | 8个字符宽度,宽度不足在头部以“0”填充 | |
+ | 包含符号位(正数+或负数—) | |
, | 组分隔符 | |
- | 左对齐(默认是右对齐) | |
.3 | 保留3位小数 | |
10.3 | 表示10个字符宽度,保留三位小数(默认右对齐) |
import java.util.Calendar;
import java.util.Locale;
public class IntegerText {
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"
}
}
TheDecimalFormat Class
可以使用java.text.DecimalFormat
格式化十进制数字的输出,包括前/后导零、前后缀、组分隔符、小数点。尽管使用DecimalFormat可以灵活控制输出的格式,另一面它也增加了代码的复杂度。
如下:通过模式patten构造DecimalFormat的对象myFormatter,接着调用format()方法(从NumberFormat继承过来的),格式化输出字符串。
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); //-->123456.789 ###,###.### 123,456.789
customFormat("###.##", 123456.789); //-->123456.789 ###.## 123456.79
customFormat("00.000", 123.7876); //-->123.7876 00.000 123.788
customFormat("$###,###.###", 12345.67); //-->12345.67 $###,###.### $12,345
}
}
| |||
数值 | Pattern | 输出 | 说明 |
123456.789 | ###,###.### | 123,456.789 | ‘#’ 代表了一个阿拉伯数字,‘,’为组分隔符,‘.’用于分割整数和小数 |
123456.789 | ###.## | 123456.79 | 数值有三位小数,而模式里只用两个,会通过四舍五入保留两位小数 |
123.78 | 000000.000 | 000123.780 | ‘0’代表了一个阿拉伯数字,位数不足需要在前或后一零补充,注意其与‘#’的区别。 |
12345.67 | $###,###.### | $12,345.67 | 以美元符号‘$’开头,保留三位小数,且组分割为3 |
tips:组分隔符“,”通常用于千位,但是在某些国家/地区中回用于分隔万位(如中国)。分组大小是分组字符之间的固定数字位数,例如100,000,000 是 3,而 1,0000,0000 则是 4。如果使用具有多个分组字符的模式,则最后一个分隔符和整数结尾之间的间隔才是使用的分组大小。所以 "#,##,###,####" == "######,####" =="##,####,####"。 即“123456.789”的模式为“###,#,##.###”,其输出为“12,34,56.789”。
基本算数运算之外
java除了支持各种基本的算术运算(+, -, *, /, 和 %)之外,也为各种复杂的数学运算提供了工具类Math。通过Math类可以完成指数、对数、反三角函数等复杂的运算。
由于Math类的方法都是静态的,你可以在类里直接调用Math类的方法,如下:
Math.cos(angle);
tips:可以使用static import静态导入Math类,如此便不用在每个方法下上Math;import static java.lang.Math.*;
接着就可以直接在方法体里通过Math类的方法名调用Math类对应的方法:
cos(angle);
常量与基本算术方法
在Math类里包含两个常量:
Math.E, 自然底数e
Math.PI,圆周率
Math类包含了超过40个的静态方法,为了分类来谈,先列出Math里的基本算术方法:
Math的基本算术方法 | |
方法 | 描述 |
double abs(double d) | 返回参数的绝对值 |
double ceil(double d) | 取得大于或等于参数的最小整数,并以double类型返回 |
double floor(double d) | 取得小于或等于参数的最大整数,并以double类型返回 |
double rint(double d) | 取得最接近参数的某一整数(类似于四舍五入),并以double类型返回 |
long round(double d) | 返回最接近参数的 |
double min(double arg1, double arg2) | 返回两个数中较小的那一个 |
double max(double arg1, double arg2) | 返回两个数中较大的那一个 |
BasicMathDemo演示了如何去使用Math的基本算术方法:
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)); //-->The absolute value of -191.635 is 191.635
System.out.printf("The ceiling of " +
"%.2f is %.0f%n",
b, Math.ceil(b)); //-->The ceiling of 43.74 is 44
System.out.printf("The floor of " +
"%.2f is %.0f%n",
b, Math.floor(b)); //-->The floor of 43.74 is 43
System.out.printf("The rint of %.2f " +
"is %.0f%n",
b, Math.rint(b)); //-->The rint of 43.74 is 44
System.out.printf("The max of %d and " +
"%d is %d%n",
c, d, Math.max(c, d));//-->The max of 16 and 45 is 45
System.out.printf("The min of of %d " +
"and %d is %d%n",
c, d, Math.min(c, d));//-->The min of of 16 and 45 is 16
}
}
Math里指数与对数运算:
下表列出了在Math里关于指数与对数运算的方法:
指数、对数运算的方法 | |
方法 | 描述 |
double exp(double d) | 返回自然底数e的d次方幂的值 |
double log(double d) | 返回 |
double pow(double base, double exponent) | 返回base的exponent次方的值 |
double sqrt(double d) | 返回d的算术平方根 |
Demo:ExponentialDemo
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); //-->The value of e is 2.7183
System.out.printf("exp(%.3f) " +
"is %.3f%n",
x, Math.exp(x));//-->exp(11.635) is 112983.831
System.out.printf("log(%.3f) is " +
"%.3f%n",
x, Math.log(x));//-->log(11.635) is 2.454
System.out.printf("pow(%.3f, %.3f) " +
"is %.3f%n",
x, y, Math.pow(x, y));//-->pow(11.635, 2.760) is 874.008
System.out.printf("sqrt(%.3f) is " +
"%.3f%n",
x, Math.sqrt(x));//-->sqrt(11.635) is 3.411
}
}
Math里三角函数运算
下表列出了Math里关于三角函数的方法,需要注意的是,这些方法的参数都是以弧度制来表示的——换句话说就是,你需要将角度转换为弧度。可以使用方法toRadians(),将角度转换为弧度。
三角函数运算的方法 | |
方法 | 描述 |
double sin(double d) | 返回角的三角正弦值 |
double cos(double d) | 返回角的三角余弦值 |
double tan(double d) | 返回角的三角正切值 |
double asin(double d) | 返回一个值的反正弦值;返回的角度范围在 -pi/2 到pi/2 之间。 |
double acos(double d) | 返回一个值的反余弦值;返回的角度范围在 0.0 到pi之间。 |
double atan(double d) | 返回一个值的反正切值;返回的角度范围在 -pi/2 到pi/2 之间。 |
double atan2(double y, double x) | 将矩形坐标 ( |
double toDegrees(double d) | 角度和与弧度的相互转换方法 |
Demo: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);
//-->The value of pi is 3.1416
System.out.format("The sine of %.1f " +
"degrees is %.4f%n",
degrees,Math.sin(radians));
//-->The sine of 45.0 degrees is 0.7071
System.out.format("The cosine of %.1f " +
"degrees is %.4f%n",
degrees, Math.cos(radians));
//-->The cosine of 45.0 degrees is 0.7071
System.out.format("The tangent of %.1f " +
"degrees is %.4f%n",
degrees, Math.tan(radians));
//-->The tangent of 45.0 degrees is 1.0000
System.out.format("The arcsine of %.4f " +
"is %.4f degrees %n",
Math.sin(radians), Math.toDegrees(Math.asin(Math.sin(radians))));
//-->The arcsine of 0.7071 is 45.0000 degrees
System.out.format("The arccosine of %.4f " +
"is %.4f degrees %n",
Math.cos(radians), Math.toDegrees(Math.acos(Math.cos(radians))));
//-->The arccosine of 0.7071 is 45.0000 degrees
System.out.format("The arctangent of %.4f " +
"is %.4f degrees %n",
Math.tan(radians), Math.toDegrees(Math.atan(Math.tan(radians))));
//-->The arctangent of 1.0000 is 45.0000 degrees
}
}
随机数
Math类的random()方法可以产生大于等于0.0
且小于1.0
的(伪)随机数(0 <= Math.random()<1),如此,你便能利用这个函数产生各中范围的随机数,如
要产生0~9的随机数:
int number = (int)(Math.random() * 10); //(0 <= number < 10)
如产生5~9的随机数:
int number = (int)(Math.random() * 5) + 5;
附:使用Math.random()可以产生一个随机数。如果需要产生一系列随机数,可以创建 java.util.Random的对象,并调用对应的方法。
转载于:https://blog.51cto.com/peiquan/1282169